在MVC ASP.net中使用X-editable时避免重复的最好方法

Best way not to repeat yourself while using X-editable in MVC ASP.net

本文关键字:方法 net ASP MVC X-editable      更新时间:2023-09-26

我刚刚开始使用一个很好的js库来编辑表单元素。这是库的链接。

它工作得很好,你可以在适当的地方更新你的表单元素。但是,您需要为每个单独的表单元素创建一个操作。

示例:

<a href="#" class="EditableSection" data-type="text" data-pk="@Model.id" data-name="Name" data-url="@Url.Action("_EditName", "User", new { Model.id})" data-title="Edit Name">@Model.Name</a>
<a href="#" class="EditableSection" data-type="text" data-pk="@Model.id" data-name="MiddleName" data-url="@Url.Action("_EditMiddleName", "User", new { Model.id})" data-title="Edit Middle Name">@Model.MiddleName</a>
<a href="#" class="EditableSection" data-type="text" data-pk="@Model.id" data-name="SurName" data-url="@Url.Action("_EditSurName", "User", new { Model.id})" data-title="Edit SurName">@Model.SurName</a>

在UserController中,我认为我需要有3个不同的动作,除了元素更新之外,动作的大部分内部类似。

这是一个动作:

        [HttpPost]
        public ActionResult _EditUserName(int id, int pk, string value, string name)
        {
            var user= this._userRep.First(o => o.id== pk);
            if (user!= null && user.id== id)
            {
                if (!string.IsNullOrEmpty(value))
                {
                    user.UserName= value; //this is the only line changes from one to another action respectively   user.MiddleName = value or user.SurName = value 
                    this._userRep.Update(user);
                    this._userRep.SaveChanges();
                    return new HttpStatusCodeResult(HttpStatusCode.OK);
                }
                return Json(new { status = "error", msg = "You cannot leave blank" });
            }
            return  Json(new {status="error",msg="You cannot leave blank"});
        }

我可以看到2个选项来改进使代码DRY

第一个是为每个表单元素创建一个操作,并将所有公共任务放在一个单独的方法中以调用每个操作。(我仍然认为太多的打字和混乱)

第二个选项是我关注的,但我不知道是哪个,我想在这里得到你的帮助:

创建一个公共操作作为_EditUserDetails,并使用下面的条件:

        [HttpPost]
        public ActionResult _EditUserDetails(int id, int pk, string value, string name)
        {
            var user= this._userRep.First(o => o.id== pk);
            if (user!= null && user.id== id)
            {
                if (!string.IsNullOrEmpty(value))
                {
                  if(name=user.UserName.toString())
                    user.UserName= value; 
                  else if(name=user.MiddleName.toString())
                      user.MiddleName= value; 
                  else if(name=user.MiddleName.toString())
                   user.SurName= value; 
                    this._userRep.Update(user);
                    this._userRep.SaveChanges();
                    return new HttpStatusCodeResult(HttpStatusCode.OK);
                }
                return Json(new { status = "error", msg = "You cannot leave blank" });
            }
            return  Json(new {status="error",msg="You cannot leave blank"});
        }

我无法获得用户对象变量名的名称进行比较,我也不确定这是检查它的正确方法

if(name=user.UserName.toString())//name等于表单元素名称。并且我知道user.UserName.toString()返回值而不是'UserName'

这里是代替user。UserName值,我只想使用名称本身UserName进行比较?我可以创建一个静态强类型类在这种情况下使用,但你认为这是必要的吗?为什么我不能使用对象变量的名称进行比较?

你对此的最佳实践是什么?

您可以使用反射来根据名称设置属性值。如果你使用这种方法,我建议你添加一个白名单,以防止过度发布。

<a href="#" class="EditableSection" data-type="text" data-pk="@Model.id" id="Name" data-url="@Url.Action("InlineEdit", "User", new { Model.id})" data-title="Edit Name">@Model.Name</a>
<a href="#" class="EditableSection" data-type="text" data-pk="@Model.id" id="MiddleName" data-url="@Url.Action("InlineEdit", "User", new { Model.id})" data-title="Edit Middle Name">@Model.MiddleName</a>

xeditables通过name参数传递ID,因此不需要添加"data-name"属性

    [HttpPost,
    ValidateAntiForgeryToken]
    public ActionResult InlineEdit(int pk, string value, string name)
    {
        //
        // White list to prevent overposting
        string whitelist = "Name,MiddleName,SurName";
        if (!whitelist.Contains(name))
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest, string.Format("Invalid Field {0}", name));
        };
        var user= this._userRep.First(o => o.id== pk);;
        if (user == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest, string.Format("Resource not found"));
        }
        try
        {
                this.SetPropertyValue(user, name, value);
                this._userRep.Update(user);
                this._userRep.SaveChanges();
                return new HttpStatusCodeResult(HttpStatusCode.OK);
        }
        catch (DbEntityValidationException ex)
        {
            var error = ex.EntityValidationErrors.First().ValidationErrors.First();
            this.ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest, string.Format("{0}: {1}", error.PropertyName, error.ErrorMessage));
        } 
    }

下面是一个函数,用于在将属性转换为适当的数据类型之前设置属性

    private Object SetPropertyValue(Object entity, string property, string value)
    {
        PropertyInfo propertyInfo = entity.GetType().GetProperty(property);
        if (propertyInfo != null)
        {
            Type t = propertyInfo.PropertyType;
            object d;
            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                if (String.IsNullOrEmpty(value))
                    d = null;
                else
                    d = Convert.ChangeType(value, t.GetGenericArguments()[0]);
            }
            else if (t == typeof(Guid))
            {
                d = new Guid(value);
            }
            else
            {
                d = Convert.ChangeType(value, t);
            }
            propertyInfo.SetValue(entity, d, null);
        }
        return entity;
    }

三个字段的大量代码(在这种情况下,我宁愿用户3个操作)。

如果你有很多想要更新的字段,这非常有用。