Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core Cannot Read Request Body

I have been working on ASP.NET Core from a few weeks. I was trying to achieve something based on this blog: Microservices

My project.json is as follows:

{
  "version": "1.0.0-*",
  "compilationOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {

    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-*",
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "EntityFramework.Core": "7.0.0-rc1-final",
    "EntityFramework.Commands": "7.0.0-rc1-final",
    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
    "EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.Formatters.Json": "6.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-rc1-final",
    "System.Security.Cryptography.Algorithms": "4.0.0-beta-23516"

  },

  "commands": {
    "web": "Microsoft.AspNet.Server.Kestrel",
    "ef": "EntityFramework.Commands"
  },

  "frameworks": {

    "dnxcore50": {
      "dependencies": {


      }

    }
  },

  "exclude": [
    "wwwroot",
    "node_modules"
  ],
  "publishExclude": [
    "**.user",
    "**.vspscc"
  ]
}

And ConfigureServices method in Startup.cs is as follows:

public void ConfigureServices(IServiceCollection services)
{
    //Registering Authorization Database
    AutorizationAccessRegisteration.RegisterComponents(services, Configuration);

    services.AddMvcCore()
        .AddJsonFormatters(a => a.ContractResolver = new CamelCasePropertyNamesContractResolver());

    //Add cors built in support.
    services.AddCors();

    services.AddMvcCore().AddApiExplorer();

    //Add MVC for supporting WebApi requests
    #region MVC Add

    services.AddMvc();

    services.AddMvc().AddMvcOptions(options =>
    {
        options.RespectBrowserAcceptHeader = true;

        // Input Formatters.
        options.InputFormatters.Clear();

        var jsonInputFormatter = new JsonInputFormatter()
        {
            SerializerSettings = new JsonSerializerSettings()
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
                ,
                DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
                NullValueHandling = NullValueHandling.Ignore
            }
        };


        options.InputFormatters.Add(jsonInputFormatter);

        //Output formater
        //as part of get/post request, set the header Accept = application/json or application/xml
        var jsonOutputFormatter = new JsonOutputFormatter();
        jsonOutputFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        jsonOutputFormatter.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore;
        options.OutputFormatters.Insert(0, jsonOutputFormatter);

        options.OutputFormatters.Insert(1, new XmlDataContractSerializerOutputFormatter());

    });

    #endregion
}

And here is my Confiure method in Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {

    }
    else if (env.IsStaging())
    {

    }
    else if (env.IsProduction())
    {

    }

    app.UseIISPlatformHandler();

    app.UseCors(builder =>
            builder.WithOrigins("*").AllowAnyHeader().AllowAnyMethod());

    //Middlewares addition to the pipelines:
    /// We add the middlewares in the following fashion:
    /// - Exception Handler
    /// - Logger
    /// - Authorization Handler
    /// There is a big reason of doing that.
    ///
    app.UseExceptionHandler();
    app.UseLoggerHandler();
    app.UseAuthorizationHandler();

    app.UseMvc();
}

An AuthorizationController is as follows:

[Route("api/Authorization")]
public class AuthorizationController : Controller
{
 .
     [HttpPost]
     public void Post([FromBody]string value)
     {
     }
 .
}

The Post method originally had [FromBody]string[] value. I simplified it further by making it a simple string type. I am using Advance Rest Client on Chrome to send an HTTP request. When string[] was the type I was the following values in body:

{

  ["value","sdjklgsdjlg"]

}

After simplifying the parameter, I tried sending request with the following body:

{"sdjklgsdjlg"}

tried this as well:

{"value":"sdjklgsdjlg"}

Am I missing something? I read before, the way old WebApi used to work in relation to the JSON mapping to the complex objects and normal parameters, it works in similar fashion in .NET Core.

Also I should elaborate that breakpoint is hit normally on all the middlewares and controllers. But none of the middleware seems to be able to read Request's stream related things:

context.Request variable problems

context.Request.Body errors

Kindly tell me where I am making problem. Thanks a lot!

like image 861
FreshDev Avatar asked Mar 18 '16 11:03

FreshDev


1 Answers

I am late here, but want to share the exact reason so any other user can get accurate info.

You are not able to get values at controller because you are posting data as JSON object:

{"value":"sdjklgsdjlg"} //See the curly braces represent an object.

For resolving this we need another object to bind this data to. Something like this at controller's action:

[HttpPost]
public void Post([FromBody]CustomViewModel data)
{
     ...
    //here you can get value as: data.Value
}

here CustomViewModel is a class:

public CustomViewModel
{
    public string Value { get; set; }
}

If you want to get data as per your current action signature:

[HttpPost]
public void Post([FromBody]string value)
{
     ...
}

Then, you need to pass data as JSON string in request body:

"sdjklgsdjlg" //notice without any curly braces and property name

Similarly for string array action:

[HttpPost]
public void Post([FromBody]IEnumerable<string> values)
{
     ...
}

pass JSON array of string in request body:

["item1", "item2"]
like image 199
Prateek Pandey Avatar answered Sep 19 '22 17:09

Prateek Pandey