4

Ich möchte einen benutzerdefinierten Content-Type-Validierungsfilter implementieren, sodass ein benutzerdefiniertes Fehlermodell für einen nicht unterstützten Medientyp 415 bereitgestellt werden kann.Benutzerdefinierter Content-Type-Validierungsfilter?

Etwas wie folgt aus:

public class ValidateContentTypeFilterAttribute : ActionFilterAttribute 
{ 
    private const string JsonMimeType = "application/json"; 

    public override void OnActionExecuting(ActionExecutingContext context) 
    { 
     string requestMethod = context.HttpContext.Request.Method.ToUpper(); 

     if (requestMethod == WebRequestMethods.Http.Post || requestMethod == WebRequestMethods.Http.Put) 
     { 
      if (request.ContentType != JsonMimeType) 
      { 
       // "Unsupported Media Type" HTTP result. 
       context.Result = new HttpUnsupportedMediaTypeResult(); 
       return; 
      } 
     } 
    } 
} 

Das Problem ist, dass die MVC-Pipeline "Fang" unsupported oder ungültigen Content-Type-Werte vor der Ausführung alle benutzerdefinierten Filter zu sein scheint. Selbst der Inhaltstyp "application/xml" wird abgelehnt.

Wo würde dies konfiguriert werden?

Meine MVC-Konfiguration besteht aus nicht viel mehr als das:

public void ConfigureServices(IServiceCollection services) 
{ 
    services 
     .AddMvc() 
     .AddJsonOptions(options => 
     { 
      options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
      options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Include; 
      options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 
      options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; 
      options.SerializerSettings.Converters.Add(new SquidJsonConverter()); 
     }) 
     .AddMvcOptions(options => 
     { 
      options.Filters.Add(typeof(ValidateAntiForgeryTokenAttribute)); 
      options.Filters.Add(typeof(ValidateContentTypeFilterAttribute)); 
      options.Filters.Add(typeof(ValidateAcceptFilterAttribute)); 
      options.Filters.Add(typeof(ValidateModelFilterAttribute)); 
     }); 
    ... 
} 

Antwort

5

Aktionsfilter zu spät in der Verarbeitungspipeline sind für das, was Sie versuchen, hier zu erreichen.

Die Filterausführungsreihenfolge für eine „eingehende“ Anforderung ist die folgenden:

  1. OnResourceExecuting.. Methodenaufruf Modell
  2. OnAuthorization.. Methodenaufruf
  3. Ressourcenfilter Authorization Filter
  4. Modell geschieht Bindung (dies ist Ort, an dem die Inhaltsartüberprüfung vorgenommen wird)
  5. Aktionsfilter 'OnActionExecuting.. Methodenaufruf
  6. Ausführung der Aktion

Sie können stattdessen einen Ressourcenfilter erstellen. Ein Beispiel:

public class CustomResourceFilter : IResourceFilter 
{ 
    private readonly string jsonMediaType = "application/json"; 

    public void OnResourceExecuted(ResourceExecutedContext context) 
    { 
    } 

    public void OnResourceExecuting(ResourceExecutingContext context) 
    { 
     if (context.HttpContext.Request.Method == "PUT" || context.HttpContext.Request.Method == "POST") 
     { 
      if (!string.Equals(
       MediaTypeHeaderValue.Parse(context.HttpContext.Request.ContentType).MediaType, 
       jsonMediaType, 
       StringComparison.OrdinalIgnoreCase)) 
      { 
       context.Result = new JsonResult(new { Error = "An error message here" }) { StatusCode = 415 }; 
      } 
     } 
    } 
} 

Wenn Sie alle Arten von UnsupportedMediaTypeResult Antworten ändern möchten, dann können Sie ein Ergebnis Filter stattdessen schreiben.

Die Filter-Pipeline für ausgehende Antwort ist:

  1. Aktion OnActionExecuted... Methodenaufruf
  2. Ergebnis Filter OnResultExecuting.. Methodenaufruf
  3. Filter Ergebnis Filter OnResultExecuted.. Methodenaufruf
  4. Ressourcenfilter OnResourceExecuted.. Methodenaufruf

Ein Beispiel mit einem Ergebnisfilter:

public class CustomResultFilter : ResultFilterAttribute 
{ 
    public override void OnResultExecuting(ResultExecutingContext context) 
    { 
     var result = context.Result as UnsupportedMediaTypeResult; 
     if (result != null) 
     { 
      context.Result = new JsonResult(new { Error = "An error message here" }) { StatusCode = 415 }; 
     } 
    } 
} 
+0

Ergebnisfilter sind neu für mich! Das funktioniert perfekt - danke. – davenewza

Verwandte Themen