2017-01-09 2 views
0

ich die Fehler vom Typ Required aus dem Modellzustand, bei PATCH HTTP-Anforderung zu ignorieren, wobei ich Teil-Updates am erlaubt:Fehler vom Typ entfernen von Model Erforderliche

public class ValidateModelFilterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext context) 
    { 

     if (!context.ModelState.IsValid && context.HttpContext.Request.Method == "PATCH") 
     { 

      // can't figure out this part 
      var modelStateErrors = context.ModelState.Keys.SelectMany(key => context.ModelState[key].Errors); 
      // get errors of type required from the modelstate 
      // context.ModelState.Remove("attribute_which_failed_due_to_required"); 


     } 
     if (!context.ModelState.IsValid) 
     { 
      var modelErrors = new Dictionary<string, Object>(); 
      modelErrors["message"] = "The request has validation errors."; 
      modelErrors["errors"] = new SerializableError(context.ModelState); 
      context.Result = new BadRequestObjectResult(modelErrors); 
     } 
    } 
} 

Controller Aktion:

[ValidateModelFilter] 
[HttpPatch("{id}")] 
public virtual async Task<IActionResult> Update([FromRoute] int id, [FromBody] TEntity updatedEntity) 
{ 
    TEntity entity = repository.GetById<TEntity>(id); 
    if (entity == null) 
    { 
     return NotFound(new { message = $"{EntityName} does not exist!" }); 
    } 
    repository.Update(entity, updatedEntity); 
    await repository.SaveAsync(); 
    return NoContent(); 
} 

Also, wie kann ich "erforderliche" Typfehler herausfiltern und sie aus dem Modellzustand entfernen.

Antwort

0

Leider gibt es keine bessere Option als eine Reflexion. Ich habe es geschafft, benötigte Felder mit folgendem Code zu finden.

foreach (string parameter in context.ModelState.Keys) 
{ 
    string[] parameterParts = parameter.Split('.'); 
    string argumentName = parameterParts[0]; 
    string propertyName = parameterParts[1]; 
    var argument = context.ActionArguments[argumentName]; 
    var property = argument.GetType().GetProperty(propertyName); 
    if (property.IsDefined(typeof(RequiredAttribute), true)) 
    { 
     // Your logic 
    } 
} 
+0

Code stürzt parameterParts enthält keinen Punkt –

+0

Okay, geben Sie bitte Ihre Controller-Methode zu Ihrer Frage hinzufügen. Fügen Sie auch ModelState.Keys hinzu, um Dinge zu verdeutlichen. –

+0

@IzzetYildrim ModelState.Keys gibt einfach Schlüsselnamen wie ID, Name, Farbe usw. zurück. Es enthält sogar falsche Schlüsselnamen, wenn falsche Schlüsselnamen im Körper geschrieben werden. –

-1

Hier ist, was ich getan habe:

public override void OnActionExecuting(ActionExecutingContext context) 
    { 

     if (!context.ModelState.IsValid && context.HttpContext.Request.Method == "PATCH") 
     { 
      var modelStateErrors = context.ModelState.Where(model => 
      { 
       // ignore only if required error is present 
       if (model.Value.Errors.Count == 1) 
       { 
        // assuming required validation error message contains word "required" 
        return model.Value.Errors.FirstOrDefault().ErrorMessage.Contains("required"); 
       } 
       return false; 
      }); 
      foreach (var errorModel in modelStateErrors) 
      { 
       context.ModelState.Remove(errorModel.Key.ToString()); 
      } 

     } 
     if (!context.ModelState.IsValid) 
     { 
      var modelErrors = new Dictionary<string, Object>(); 
      modelErrors["message"] = "The request has validation errors."; 
      modelErrors["errors"] = new SerializableError(context.ModelState); 
      context.Result = new BadRequestObjectResult(modelErrors); 
     } 
    } 
+0

Dies ist nicht wirklich eine feste Lösung. Sich auf eine Fehlermeldung zu verlassen, ist überhaupt keine gute Praxis. Außerdem überprüfen Sie nur die erste Fehlermeldung in Ihrem LINQ. Wenn eine Fehlermeldung "erforderliches" Wort enthält, wird Ihr Modellstatus daher ungültig. Bitte überlege, ob du meine Lösung ausprobierst. –

Verwandte Themen