WebApi - 使用反射检查表单值是否为空以便为实体设置值是否不好

本文关键字:是否 实体 设置 检查 反射 检查表 表单 WebApi | 更新日期: 2023-09-27 18:37:17

我是Web服务(WebApi)开发的新手,但到目前为止,:),这是一次很棒的经历。但是现在,我对在Web服务中处理Put()请求的方式感到困惑。

我有一个接收多部分/表单数据的 Put() 请求。在更新相应的实体之前,我必须检查表单正文值是否为空。

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

我使用了 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;
    }

上面的代码完成了这项工作,但问题是 - 这是唯一的方法还是有更好的方法来实现我想要做的事情?如果有的话,关于这些方法的指示很少,将不胜感激。

提前致谢:)

WebApi - 使用反射检查表单值是否为空以便为实体设置值是否不好

我听说过反射方法,我"慢",比其他方法慢,但是当我不知道类结构时,我已经使用它。

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

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

MCV 做得很好,其中之一是从通过 HttpRequest 发布的 html 表单中"重新创建"方法中的对象。在访问原始发布数据之前,我每次都会尝试使用此函数。

在你的情况下,你知道类型,你知道属性名称,所以我认为你可以将你的代码简化为更简单和标准的模式

例如:

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

对象产品是从 mvc 引擎为您重新创建的,因此您可以以更舒适的方式使用它