Laden...

ASP .NET 4.8 zu ASP NET 7.0: Parameterliste zu [FromBody] refactoren.

Erstellt von Christoph K. vor 11 Monaten Letzter Beitrag vor 11 Monaten 632 Views
Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 11 Monaten
ASP .NET 4.8 zu ASP NET 7.0: Parameterliste zu [FromBody] refactoren.

Hallo zuammen,

ich möchte ein (riesieges) ASP .NET 4.8 Projekt auf das neue ASP 7.0 Refactoren und bin gerade auf das erste Problem gestoßen.

Im alten ASP laufen alle Post Request einfach auf die Parameterliste der Methode ein, die dan ActionResult zurückgibt.

public ActionResult DoIt(string para1, string para2);

Dies geht ja nun nicht mehr, und mann muss alle Parameter in einer Klasse kapseln und dann in Form eines Parameters + dem Attribute [FromBody] in die Parameterliste schreiben.

Meine Frage ist, ob es hierfür ein automatisches Refectoring gibt? Oder einen Umweg, sodass der alte Weg weiterhin funktioniert?

6.911 Beiträge seit 2009
vor 11 Monaten

Hallo Christoph K.,

Dies geht ja nun nicht mehr, und mann muss alle Parameter in einer Klasse kapseln und dann in Form eines Parameters + dem Attribute [FromBody] in die Parameterliste schreiben.

Schau dir dazu Binding source parameter inference an.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

16.807 Beiträge seit 2008
vor 11 Monaten

Zitat von Christoph K.

Dies geht ja nun nicht mehr, und mann muss alle Parameter in einer Klasse kapseln und dann in Form eines Parameters + dem Attribute [FromBody] in die Parameterliste schreiben.

Nö, muss man nicht.

Der einzige Breaking Change existiert, wenn man versucht den ApiControllerfür Forms zu verwenden oder den Controllerfür Json-basierte Requests. Das wurde aber schon vor über 7 Jahren announced.

Blick in die Doku hilft übrigens sehr:
Upgrade from ASP.NET Framework to ASP.NET Core

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 11 Monaten

Hmm, ich finde leider bei den Links nichts, was mir helfen kann.

Ich bekomme es einfach nicht hin, dass ich bei einem Post Request weiterhin eine Liste von Parmetern direkt in die Parameterliste der Methode schreiben kann.

Wenn es jemand besser weiss, würde ich mich über ein konkretes Beispiel freuen.

D
615 Beiträge seit 2009
vor 11 Monaten

Hallo

Verstehe ich es richtig, du willst Json Posten auf ein "Controller" und kein Model für die einzelnen Parameter erstellen?

Wenn du das wirklich machen willst, kannst du dies indem du eine "JsonValueProviderFactory" registirert und ein "JsonValueProvider".
Somit kannst du den Support für Json nachträglich wieder einbauen 😉.

In der JsonValueProviderFactory liest du den Request aus, schaust ob es Json ist, deserialisiert den Inhalt und prüfst ob bspw. die Anzahl Parameter passen und deren Namen.... Sollte das alles passen, kannst du dem Context den JsonValueProvider mitgeben, etwa so:

public class JsonValueProviderFactory : IValueProviderFactory
 {
 public async Task CreateValueProviderAsync(ValueProviderFactoryContext context)
       {
           if (context == null)
           {
               throw new ArgumentNullException(nameof(context));
           }
          //we are only interested in "body" attribute since we are extracting the body, ignore from Query Attribute
          var parameters = context.ActionContext.ActionDescriptor.Parameters.Where(r => r.BindingInfo?.BindingSource?.Id != BindingSource.Query.Id).ToList();
          //do validation, read stream body, check if json, deserialize ...  wenn nun alles passt
          context.ValueProviders.Add(new JsonValueProvider(jObject));
      }
 }

Der JsonValueProvider kann dann etwa so aussehen

public class JsonValueProvider : IValueProvider
   {
       private readonly JObject m_jObject;
       public JsonValueProvider(JObject jObject)
       {
           m_jObject = jObject;
       }
       public bool ContainsPrefix(string prefix)
       {
           return m_jObject.ContainsKey(prefix);
       }
       public ValueProviderResult GetValue(string key)
       {
           return new ValueProviderResult(new StringValues((string)m_jObject[key]));
       }
   }

Nicht vergessen die JsonValueFactory zu registrieren im Startup

options.ValueProviderFactories.Add(new JsonValueProviderFactory());

Viel Spass

16.807 Beiträge seit 2008
vor 11 Monaten

Hmm, ich finde leider bei den Links nichts, was mir helfen kann.

Model Binding in ASP.NET Core - haste das nicht gefunden, hast nicht gesucht. Steht direkt in den Docs von ASP.NET Core.

Es gibt unterschiedliche Binding-Arten in ASP.NET Core und das API Binding basiert zu 100% auf Modellen und Attributs-basiert. Im Falle von ApiControllern war das IIRC schon immer so. Wenn man natürlich Formdata-Controller für die API missbraucht hat: jo, das tut jetzt weh.

Es gibt hier auch kein Setting, das das ändert, weil das Binding so funktionieren muss, um gewisse Szenarien unterstützen zu können.
Steht alles in den Binding Docs. Und die Docs sind super wichtig, weil wenn man die nicht liest, wird man unendlich viel Zeit verbrennen, weil man das Binding und die Reihenfolgen des Bindings nie verstehen wird.