0

我是Web服务(WebApi)开发新手,但直到现在,这是一段美妙的经历:)。但现在,我对我在Web服务中处理Put()请求的方式感到困惑。WebApi - 使用反射来检查表单值是否为空以便为实体设置值不好吗?

我有一个Put()请求接收multipart/form-data。在更新相应的实体之前,我必须检查表单体的值是否为空。

如果实体的特定属性为空,即不存在于主体中,则不应对属性进行任何更改,在这种情况下,属性将具有先前设置的值。如果某个属性的值存在于主体中,则需要更新该实体的相应值。

我使用if-else,但它导致了很多代码,因为我有大约10个实体属性。所以我删除了所有if-else并使用反射来实现此目的。下面是我现在用目前的代码,

[AuthorizationRequired] 
    [Route("v1/product/updateproduct/")] 
    [HttpPut] 
    public bool Put() 
    { 
     var httpRequest = HttpContext.Current.Request; 
     string pdfFolderPath = HttpContext.Current.Server.MapPath("~/Pdf/"); 
     string imageFolderPath = HttpContext.Current.Server.MapPath("~/Images/"); 
     ProductEntity productToUpdate = new ProductEntity(); 

     int id = int.Parse(httpRequest["ProductId"].ToString()); 

     if (id > 0) 
     { 
      //Get the existing product entity for the ID 
      ProductEntity existingProduct = _productServices.GetProductById(id); 

      if (existingProduct != null) 
      { 
       //Check if any files are sent in the PUT Request 
       //If there are files with appropriate names, then delete the existing files with the new files sent 
       if (httpRequest.Files.Count > 0) 
       { 
        //Handle Files. 
       } 

       //Updating the changed properties of Product by using Reflection. 
       PropertyInfo[] properties = productToUpdate.GetType().GetProperties(); 

       foreach (PropertyInfo property in properties) 
       { 
        //Check if the property of the Product class exists in the Form Body of Put. 
        //If it exists, take the corresponding value of property and update it to the product. 
        //If it doesn't exist, retain the value present in the existing product as it is. 

       if (httpRequest.Form.AllKeys.Contains(property.Name, StringComparer.OrdinalIgnoreCase)) 
       { 
        int formPropertyIndex = Array.FindIndex(httpRequest.Form.AllKeys, str => str.Equals(property.Name, StringComparison.OrdinalIgnoreCase)); 
        string propertyToFind = httpRequest.Form.AllKeys[formPropertyIndex]; 

        if (String.Equals(propertyToFind, "FacilityId", StringComparison.OrdinalIgnoreCase)) 
        { 
         productToUpdate.GetType().GetProperty(propertyToFind, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).SetValue(productToUpdate, Convert.ToInt32(httpRequest[property.Name])); 
        } 
        else 
        { 
         productToUpdate.GetType().GetProperty(propertyToFind, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).SetValue(productToUpdate, httpRequest[property.Name].ToString()); 
        } 
       } 
       else 
        { 
         var existingValue = existingProduct.GetType().GetProperty(property.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(existingProduct); 
         productToUpdate.GetType().GetProperty(property.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).SetValue(productToUpdate, existingValue); 
        } 
       } 

       if (productToUpdate.ImagePath == null) 
        productToUpdate.ImagePath = existingProduct.ImagePath; 
       if (productToUpdate.AR_PdfPath == null) 
        productToUpdate.AR_PdfPath = existingProduct.AR_PdfPath; 
       if (productToUpdate.AR_Alt_PdfPath == null) 
        productToUpdate.AR_Alt_PdfPath = existingProduct.AR_Alt_PdfPath; 
       if (productToUpdate.EN_PdfPath == null) 
        productToUpdate.EN_PdfPath = existingProduct.EN_PdfPath; 
       if (productToUpdate.EN_Alt_PdfPath == null) 
        productToUpdate.EN_Alt_PdfPath = existingProduct.EN_Alt_PdfPath; 

       //Update LastModifiedBy & LastModifiedAt 
       string token = httpRequest.Headers.GetValues("Token").ToList().FirstOrDefault(); 
       UserEntity user = _tokenServices.GetUserDetailsForToken(token); 
       productToUpdate.LastModifiedBy = user.UserName; 
       productToUpdate.LastModifiedAt = DateTime.Now; 

       return _productServices.UpdateProduct(id, productToUpdate); 
      } 
      else 
      { 
       return false; 
      } 
     } 
     return false; 
    } 

上面的代码做工作,但问题是 - 这是唯一的办法或者有什么更好的办法来实现什么,我试图做的?如果有的话,那些方法上的指针很少会被真正赞赏。

感谢提前:)

+0

?:或??运算符可能有助于避免if语句在很多情况下 – Kira

+0

您可以发布“put”方法的代码吗? –

+0

@Anand Yeah null合并运算符会很好。但是,如果我有太多的属性,我会重复所有属性的操作。 – iamyogish

回答

2

我听说过反射的方法,我的“慢”,比其他的更慢,但我已经alwais使用它时,我不知道的类结构。

如果你知道类结构是一个好主意,使用他的属性。

如果您可以修改类,您应该使用数据注解验证(https://msdn.microsoft.com/en-us/library/dd901590(VS.95).aspx)来检查对象。

MCV做得非常好,其中一个是通过HttpRequest发布的html表单中的“重新创建”方法中的对象。我会尝试每次使用这个功能之前访问原始发布的数据。

你的情况,你知道的类型,你知道属性名,所以我觉得比你可以在你的代码减少到一个更简单和标准模式

例如:

[HttpPut] 
public HttpResponseMessage Put(int productId, [FromBody] Product product) 
{ 
//.. 
} 

目标物品重建从mvc引擎给你,所以你可以以更舒适的方式使用它

+0

但是我的Put()请求是multipart/form-data,所以我可以使用这个原型吗? public HttpResponseMessage Put(int productId,[FromBody] Product product); – iamyogish

+0

但是我使用了相同的模式来帮助MVC使用[FromBody]从formdata重新创建对象。但不知道如何将它用于多部分/表单数据。 – iamyogish

+1

MVC使用模型联编程序绑定来自客户端的值和操作结果的参数。如果你知道你的类结构,并相应地从客户端传递数据,MVC将绑定该属性与相应的值 – Kira