ASP.NET Core WebAPI:自定义InputFormatter验证模型状态

时间:2019-09-03 12:12:56

标签: c# asp.net-core-webapi asp.net-core-2.2

我使用自定义InputFormatters从请求主体在API请求中接收的通用请求中创建请求的子集。

var reqModel = new XmlSerializer(CurrentType).Deserialize(xmlDoc.CreateReader());
SubSetRequest model = ConvertToSubSetRequestObject(reqModel as BigRequest);
return InputFormatterResult.Success(model); 

控制器ModelState.IsValid中的当前位置不是指向SubSetRequest而是指向BigRequest,我已经收到了请求正文

 public ActionResult<object> Calculate(SubSetRequest request)
 {           
   if (!ModelState.IsValid){ }
   // other codes..
 }

任何想法我们如何针对ModelState类型验证SubSetRequest

重要类别:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvcCore(options =>
   {
     options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
     options.InputFormatters.Insert(0, new XMLDocumentInputFormatter());
   }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
   .AddXmlSerializerFormatters()
   .AddXmlDataContractSerializerFormatters();
 }

BigRequest.cs

 [System.SerializableAttribute()]
 public class BigRequest
 {
   public string Name { get; set; }
   public string Email { get; set; }
   public string Address { get; set; }
   public string Company { get; set; }
   public string Designation { get; set; }
   public string CompanyAddress { get; set; }
  }

SubSetRequest.cs

[System.SerializableAttribute()]
public class SubSetRequest
{
    public string Name { get; set; }
    [Required] //This should tiger **Validation** error 
    public string Email { get; set; }
    public string Address { get; set; }  
}

XMLDocumentInputFormatter.cs

internal class XMLDocumentInputFormatter : InputFormatter
{
  private Type CurrentType { get; set; }
  public XMLDocumentInputFormatter()
  {
    SupportedMediaTypes.Add("application/xml");
  }
  public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
  {
    using (var streamReader = new StreamReader(context.HttpContext.Request.Body))
    {
      CurrentType = typeof(BigRequest);
      var xmlDoc = await XDocument.LoadAsync(streamReader, LoadOptions.None, CancellationToken.None);
      var reqModel = new XmlSerializer(CurrentType).Deserialize(xmlDoc.CreateReader());
      var model = ConvertToSubSetRequestObject(reqModel as BigRequest);
      return InputFormatterResult.Success(model);
     }
   }

  public SubSetRequest ConvertToSubSetRequestObject(BigRequest request)
  {
     var retObject = new SubSetRequest
     {
       Name = request.Name,
       Address = request.Address
     };
     return retObject;
   }
}

ValueController.cs

[HttpPost]
[Route("/api/Value/Calculate")]
public virtual ActionResult<object> Calculate(SubSetRequest request)
{
  TryValidateModel(request);
  if (ModelState.IsValid) // is giving as TRUE, even if EMAIL is NULL
   {
     var context = new ValidationContext(request, serviceProvider: null, items: null);
     var results = new List<ValidationResult>();
     // this is working properly 
     var isValid = Validator.TryValidateObject(request, context, results);
    }
   return new ActionResult<object>(request.ToString());
 }

0 个答案:

没有答案