HttpPost [FromForm] Всегда содержит ноль - PullRequest
0 голосов
/ 28 июня 2018

Я не могу связать [FromForm] в моем IActionResult (ASP.NET Core 2) из ​​настольного приложения C #.

В моем настольном приложении C # у меня есть следующий код:

private void SendStats ( object state )
{
    double aCpu = ( ( double )AppDomain.CurrentDomain.MonitoringTotalProcessorTime.Ticks / this.totalRunningTime.Ticks ) * 100;
    double aMemory = ( double )AppDomain.MonitoringSurvivedProcessMemorySize / 1048576;
    string version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();

    Stats anStats = new Stats( this.ID, aCpu, aMemory, version );

    using ( WebRequestHandler handler = new WebRequestHandler() )
    {
        using ( HttpClient client = new HttpClient( handler ) )
        {
            client.BaseAddress = new Uri( STATS_SERVER_URL );
            client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue( "application/json" ) );

            try
            {
                var content = new StringContent( anStats.ToJSONString(), Encoding.UTF8, "application/x-www-form-urlencoded" );

                using ( HttpResponseMessage response = client.PostAsync( STATS_SERVER_URL, content ).Result )
                {
                    if ( response.IsSuccessStatusCode )
                    {
                        // Do nothing
                    }
                } 
            }
            catch ( System.AggregateException ax )
            {
                if ( !( ax.InnerException is HttpRequestException ) )
                    throw;
            }
        }
    }

    this.totalRunningTime += STATS_COLLECTION_PERIOD;
}

В классе "Моя статистика" есть:

using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.IO;

namespace MyNamespace.Stats
{
    [DataContract]
    public class Stats
    {
        [DataMember]
        private string id;

        [DataMember]
        private double cpu;

        [DataMember]
        private double mem;

        [DataMember]
        private string version;

        public Stats ( string anId, double aCpu, double aMemory, string aVersion )
        {
            this.id = anId;
            this.cpu = aCpu;
            this.mem = aMemory;
            this.Version = aVersion;
        }

        public string ToJSONString ()
        {
             DataContractJsonSerializer aSerializer = new DataContractJsonSerializer ( typeof( Stats ) );

             using ( MemoryStream aMemStream = new MemoryStream() )
             {
                 aSerializer.WriteObject( aMemStream, this );

                 aMemStream.Position = 0;

                 using ( StreamReader aStreamReader = new StreamReader ( aMemStream ) )
                 {
                      return aStreamReader.ReadToEnd();
                 }
            }
       }
   }
}

В моем приложении ASP.NET Core 2 у меня есть следующий код:

[HttpPost("{productKey}")]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult Create(string productKey, [FromForm] LegacyStatViewModel item)
{
    NewUsageViewModel aNewUsageViewModel = new NewUsageViewModel
    {
        Cpu = Convert.ToInt32(item.Cpu),
        BinaryVersion = (item.Version == null ? "UNKNOWN" : item.Version),                
        LastConnection = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
        Memory = Convert.ToInt32(item.Mem),
        ProductKey = productKey               
    };

    _context.AspNetNewUsages.Add(aNewUsageViewModel);
    _context.SaveChanges();

    return CreatedAtRoute("GetStat", new { ProductKey = aNewUsageViewModel.ProductKey }, item);
}

И, наконец, LegacyStatViewModel имеет следующий код:

namespace MyApp.Models.StatsViewModels
{
    public class LegacyStatViewModel
    {
        public string Id { get; set; }

        public double Cpu { get; set; }

        public double Mem { get; set; }

        public string Version { get; set; }
    }
}

IActionResult вызывается корректно из настольного приложения. Параметр ProductKey имеет ожидаемое значение, но все поля элемента имеют нулевое значение или 0.

Примечание: я не могу изменить приложение для рабочего стола.

1 Ответ

0 голосов
/ 28 июня 2018

Я не могу изменить приложение для настольного компьютера.

Клиент отправляет неверные данные.

Говорит, что отправляет данные формы, но отправляет JSON.

Сервер должен будет взять необработанные данные из тела запроса и выполнить соответствующий анализ, поскольку клиент не может измениться. (что является плохим дизайном IMO, поскольку вы утратили преимущество встроенных функций фреймворка.)

[HttpPost("{productKey}")]
public IActionResult Create(string productKey, [FromBody] string rawData ) {
    LegacyStatViewModel item = JsonConvert.DeserializeObject<LegacyStatViewModel>(rawData);
    if(item != null){
        NewUsageViewModel aNewUsageViewModel = new NewUsageViewModel {
            Cpu = Convert.ToInt32(item.Cpu),
            BinaryVersion = (item.Version == null ? "UNKNOWN" : item.Version),                
            LastConnection = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
            Memory = Convert.ToInt32(item.Mem),
            ProductKey = productKey               
        };

        _context.AspNetNewUsages.Add(aNewUsageViewModel);
        _context.SaveChanges();

        return CreatedAtRoute("GetStat", new { ProductKey = aNewUsageViewModel.ProductKey }, item);
    }
    return BadRequest();
}

Это действие будет правильно работать только для этого клиентского запроса, поскольку вы знаете, что он фактически отправляет JSON, а не формирует закодированные данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...