wake-up-neo.com

ASP.NET Core kann den Anforderungstext nicht lesen

Ich habe seit ein paar Wochen an ASP.NET Core gearbeitet. Ich habe versucht, etwas auf der Grundlage dieses Blogs zu erreichen: Microservices

Mein project.json lautet wie folgt:

{
  "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"
  ]
}

Die ConfigureServices-Methode in Startup.cs lautet wie folgt:

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
}

Und hier ist meine Confiure-Methode 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();
}

Ein AuthorizationController lautet wie folgt:

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

Die Post-Methode hatte ursprünglich [FromBody]string[] value. Ich habe es weiter vereinfacht, indem ich einen einfachen string-Typ gemacht habe. Ich verwende Advance Rest Client in Chrome, um einen HTTP request zu senden. Wenn string[] der Typ war, hatte ich die folgenden Werte in body:

{

  ["value","sdjklgsdjlg"]

}

Nachdem ich den Parameter vereinfacht hatte, habe ich versucht, eine Anfrage mit folgendem Text zu senden:

{"sdjklgsdjlg"}

versuchte es auch:

{"value":"sdjklgsdjlg"}

Fehlt mir etwas? Ich habe zuvor gelesen, wie früher WebApi in Bezug auf die JSON-Zuordnung zu den komplexen Objekten und normalen Parametern verwendet wurde, es funktioniert auf ähnliche Weise in .NET Core.

Ich sollte auch darauf eingehen, dass breakpoint auf allen Middlewares und Controllern normalerweise getroffen wird. Aber keine der Middleware scheint in der Lage zu sein, die Stream-bezogenen Dinge von Request zu lesen:

 context.Request variable problems

 context.Request.Body errors

Sagen Sie mir bitte, wo ich Probleme mache. Danke vielmals!

9
FreshDev

[FromBody] verwendet die registrierten Formatierer, um den gesamten Rumpf der übermittelten Daten in den einzelnen Parameter zu decodieren, auf den er angewendet wird. Standardmäßig akzeptiert der einzige registrierte Formatierer JSON.

In JSON gibt es keine gültige Möglichkeit, einen String direkt darzustellen - {"sdjklgsdjlg"} ist kein gültiger JSON-Code, {"value":"sdjklgsdjlg"} ist, wird jedoch nicht in einen einfachen Stringparameter deserialisiert. EDIT: Siehe die Antwort von @tmg, dies kann mit der Syntax { "": "sdjklgsdjlg" } erfolgen.

Daher benötigen Sie eine bestimmte Modellklasse, um die Eingabe darzustellen, die Sie vom Körper erhalten möchten, z. B .:

public class AuthRequest {
    public string Value { get; set; }
}

Dann sollten Sie in der Lage sein, erfolgreich zu tun:

[Route("api/Authorization")]
public class AuthorizationController : Controller
{
    [HttpPost]
    public void Post([FromBody]AuthRequest authReq)
    {
        // authReq.Value should have your value in
    }
}

Wenn Sie jetzt { "Value": "some value" } hier posten, sollte es das tun, was Sie erwarten.

4
Mark Hughes

Mark Hughes Antwort ist bis zu einem gewissen Punkt korrekt. Wenn Sie einen Json dieses Formats bereitstellen, sollte { "": "sdjklgsdjlg" } model binder in der Lage sein, ihn an ein einfaches String-Modell zu binden, ohne dass das Wrapper-Modell benötigt wird.

3
tmg

Das funktioniert für mich:

[HttpPost]
public async Task<IActionResult> CreateApp([FromQuery]string userId)
{
    string appDefinition = await new StreamReader(Request.Body).ReadToEndAsync();
    var newAppJson = JObject.Parse(appDefinition);
...
3
bc3tech

Sie können auch so etwas tun:

[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]dynamic value)
{
   //...
}

oder user [FromQuery] und übergeben Sie direkt einen Querystring-Wert.

1
Luca Ghersi

Ich bin spät dran, möchte aber den genauen Grund mitteilen, damit jeder andere Benutzer genaue Informationen erhalten kann.

Sie können keine Werte am Controller abrufen, da Sie Daten als JSON-Objekt buchen:

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

Zur Lösung dieses Problems benötigen wir ein anderes Objekt, an das diese Daten gebunden werden. So etwas bei der Controller-Aktion:

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

hier ist CustomViewModel eine Klasse:

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

Wenn Sie Daten gemäß Ihrer aktuellen Aktionssignatur abrufen möchten:

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

Dann müssen Sie Daten als JSON-String im Anforderungshauptteil übergeben:

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

Ähnlich für die String-Array-Aktion:

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

Übergeben Sie das JSON-Array der Zeichenfolge im Anforderungstext:

["item1", "item2"]
1
Prateek Pandey

Sie sollten die RC2-Version aller Ihrer Abhängigkeiten verwenden.
Es gibt https://github.com/aspnet/KestrelHttpServer/issues/915 Ich habe festgestellt, dass die Version von System.Threading.Tasks.Extensions standardmäßig 4.0.0 ist. Daher sollten Sie die Version dieses Pakets explizit in der Datei project.json angeben:

"System.Threading.Tasks.Extensions": "4.0.0-rc2-24027"