10

Ich bin ziemlich neu in MVC, so hoffe ich, es gibt eine Lösung für mein Problem. Ich verwende Hardware von Drittanbietern, um mit meiner MVC-Web-API zu kommunizieren. Die Hardware sendet Anfragen in einem JSON-Format, das ich perfekt extrahieren kann. Ich bin jedoch dabei, die Parameter dieser Anfragen aufgrund von Konflikten in bindende Modellobjekte zu ändern.Inhalt Header für MVC POST Anfrage überschreiben

E.G.

 Public Function POSTRequest(Action As String, Stamp As String) As HttpResponseMessage 
      ... 
     End Function 

     Public Function POSTRequest(Action As String, OpStamp As String) As HttpResponseMessage 
      ... 
     End Function 

Also diese beiden Methoden teilen sich die gleiche Calling Card, so dass sie beide nicht in der gleichen Controller existieren können.

Aus diesem Grund habe ich Modell Bindungs ​​Objekte erstellt stattdessen diese Parameter zu beherbergen. Das Problem ist, sobald ich dies mache, beschwert sich die Web-API über die Anfrage, dass der "Content-Type" nicht definiert ist. Wenn Sie es betrachten, sendet die Hardware von Drittanbietern keinen Inhaltstyp mit der Anforderung. Im Internet habe ich festgestellt, dass dies dazu führt, dass der Browser es als Inhaltstyp "application/octet-stream" behandelt. Dies kann dann nicht in das als Parameter definierte Bindungsobjekt übersetzt werden.

Wir haben keine Kontrolle über die Hardware von Dritten, so dass wir den Inhaltstyp für diese Anforderungen nicht definieren können. Meine Frage ist also, gibt es eine Möglichkeit, diese Anfragen abzufangen und ihnen einen Inhaltstyp hinzuzufügen? Oder noch einen anderen Weg?

Antwort

5

Ich glaube, Sie einen ActionFilterAttribute verwenden können. Siehe Dokumentation: Creating Custom Action Filters.

In Ihrem Fall können Sie die folgende Probe (in C#, da meine VB Fähigkeiten sind veraltet) verwenden. Es überschreibt jede Anforderung Content-Type Header mit der Anwendung/JSON Wert. Bitte beachten Sie, dass Sie es möglicherweise verbessern müssen, um jede Art von HttpContent zu unterstützen (zum Beispiel glaube ich nicht, dass dies für MultiPart-Anfragen verwendet werden sollte).

public class UpdateRequestAttribute: ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     actionContext.Request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); 
     base.OnActionExecuting(actionContext); 
    } 
} 

Dann fügen Sie dieses Attribut zu Ihrem Controller-Klasse, zum Beispiel:

[UpdateRequest] 
public class HomeController : ApiController 
{ 
    //[...] 
} 

In diesem Fall werden alle Anfragen an die Heimsteuerung ihre Content-Type außer Kraft gesetzt haben.


Alternativ können Sie auch eine benutzerdefinierte HTTP Message Handlers schreiben, die sehr früh in der Pipeline aufgerufen wird und nicht an einen bestimmten Controller begrenzt werden. Überprüfen Sie das folgende Bild, um zu verstehen, wie eine Anfrage vom Server verarbeitet wird.

ASP.net Server Side handlers

Zum Beispiel wird diese Meldung Handler das Anforderungs Content-Type zu application/json wenn es derzeit leer.

public class CustomMessageHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     if (request.Content.Headers.ContentType == null) 
     { 
      request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); 
     } 
     return base.SendAsync(request, cancellationToken); 
    } 
} 

Schließlich ist hier, wie WebApiConfig zu aktualisieren, um Ihre Nachrichten-Handler in die Pipeline hinzuzufügen:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     config.MessageHandlers.Add(new CustomMessageHandler()); 

     // Other configuration not shown... 

    } 
} 
1

Sie können durch die Definition Strecke attribute.This in einem gleichen Controller beide Methoden haben So können Sie Modellbindungsattribute vermeiden.

[Route("Request1")] 
Public Function POSTRequest(Action As String, Stamp As String) As HttpResponseMessage 
      ... 
     End Function 
     [Route("Request2")] 
     Public Function POSTRequest(Action As String, OpStamp As String) As HttpResponseMessage 
      ... 
     End Function 

Vergessen Sie nicht, Attribut zu aktivieren, indem Sie das Routing der MapHttpAttributeRoutes in Ihrer webapiconfig.vb Datei hinzufügen

Public Module WebApiConfig 
    Public Sub Register(ByVal config As HttpConfiguration) 
     ' Web API configuration and services 

     ' Web API routes 
     config.MapHttpAttributeRoutes() 

     config.Routes.MapHttpRoute(
      name:="DefaultApi", 
      routeTemplate:="api/{controller}/{id}", 
      defaults:=New With {.id = RouteParameter.Optional} 
     ) 
    End Sub 
End Module