简体   繁体   English

在MVC ASP.net中使用X-editable时不要重复自己的最佳方法

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

I have just started using a nice js library to edit form elements in place. 我刚开始使用一个很好的js库来编辑表单元素。 Here is the link for the library. 是图书馆的链接。

It works well that you can just right in place update your form elements. 它很好,您可以恰到好处地更新表单元素。 However you will need to create an action for each individual form element. 但是,您需要为每个单独的表单元素创建一个操作。

An example : 一个例子 :

<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>

In UserController I believe that I will need to have 3 different actions for each and most of the inside of the action similar apart from the the element which gets updated. 在UserController中,我相信我需要为每个动作内部设置3个不同的动作,并且与更新的元素类似。

here is one of the actions : 这是其中一个动作

        [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"});
        }

I can see 2 options to improve make the code DRY. 我可以看到2个选项来改进代码DRY。

First one is create one action for each form element and put all the common task in a separate method to call on each action. 一个是为每个表单元素创建一个操作,并将所有常见任务放在一个单独的方法中以调用每个操作。 (Still I believe too much typing and mess) (我仍然相信太多的打字和混乱)

Second option what I focus on but I could not figure it out which I would like to get your help here : 我关注的第二个选项,但我无法弄明白我想在这里得到你的帮助:

Create a common action as _EditUserDetails and use condition something below : 创建一个公共操作作为_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"});
        }

I cannot get the name of the user object variable name for the comparison and also I am not sure this is the correct way of checking it . 我无法获得比较的用户对象变量名称,我也不确定这是检查它的正确方法

if(name=user.UserName.toString()) // name is equal to form element name. if(name=user.UserName.toString()) // name等于表单元素名称。 and I know user.UserName.toString() returns the value instead of 'UserName' 我知道user.UserName.toString()返回的值而不是'UserName'

here is instead of user.UserName value I just would like to use the name itself which is UserName for the comparison? 这里是而不是user.UserName值我只想使用名称本身的UserName进行比较? I can create a static strongly typed class to use in this conditions but do you think this is necessary? 我可以创建一个静态强类型类来在这种情况下使用,但你认为这是必要的吗? why I cannot just use the name of the object variables for comparison? 为什么我不能只使用对象变量的名称进行比较?

What would be your best practise for this? 你最好的做法是什么?

You can user reflection to set the property value based on the name. 您可以使用反射来根据名称设置属性值。 If you use this approach I would advise you to add a white list to prevent over posting. 如果您使用此方法,我建议您添加白名单以防止过度发布。

<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 passes the ID through in the name parameter so no need to add a "data-name" attribute 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));
        } 
    }

Here is a function to set the property before converting it to the appropriate data type 这是一个在将属性转换为适当的数据类型之前设置属性的函数

    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;
    }

A lot of code for three fields (I would rather user 3 actions in that case). 三个字段的很多代码(在这种情况下我宁愿使用3个操作)。 Very useful if you have a lot of fields you want to update. 如果您要更新许多字段,这非常有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM