更新模型仅更改了属性

时间:2013-08-05 06:00:25

标签: c# asp.net-mvc-4

是否可以仅从视图中跟踪模型更改的值。例如,我的模型名为SampleModel

public class SampleModel
{
   public int Id { get; set; }
   public string ImageUrl1 { get; set; }
   public string ImageUrl2 { get; set; }
}

如何仅检查控制器内部更改的模型值?

4 个答案:

答案 0 :(得分:1)

控制器只知道请求中有哪些值。要可靠地确定已更改的内容,您需要将接收到的模型与从控制器操作逻辑或业务层逻辑中的(repository / dao / dal / whatever)获取的当前模型进行比较,只要它们更适合您的应用程序。< / p>

答案 1 :(得分:0)

然后你可能需要某种形式的DTO模式。

例如,假设您想要为“创建”和“编辑”操作设置不同的表单,那么您将进行以下操作:

新表格的一个类:

public class NewSampleModelDto
{
   [Required]
   public string ImageUrl1 { get; set; }

   public NewSampleModelDto() { }

   public SampleModel ToModel() 
   {    
        return new SampleModel 
        { 
            ImageUrl1 = ImageUrl1
        };
   {
}

编辑表单的一个类:

public class EditSampleModelDto
{
   public int Id { get; set; }

   [Required]
   public string ImageUrl2 { get; set; }

   // default constructor required for mvc model binding
   public EditSampleModelDto() { }

   // from model ==> dto
   public EditSampleModelDto(SampleModel sampleModel) 
   { 
        Id = sampleModel.Id;
        ImageUrl2 = sampleModel.ImageUrl2;
   }

   // from dto ==> model
   public void UpdateModel(SampleModel sampleModel) 
   {    
        sampleModel.ImageUrl2 = ImageUrl2;
   {
}

这使您可以灵活地为每个表单定义自定义验证逻辑。 为了保持代码DRY,您可以创建一个基本的SampleModelDto,您可以在其中提供处理所有'model ==&gt;的构造函数。 dto'逻辑。您还可以在此处将属性显示属性。

无论如何,如果您在表单中使用这些DTO并将其提交给控制器,则可以更自由地指定验证和更新逻辑。

答案 2 :(得分:0)

如果我正确理解你想要的东西,你可以使用jQuery来达到这个目的。例如,您可以为旧值创建隐藏的div并将其与当前值进行比较。如果当前值等于旧值,则无需发布。

<script>
$('oldValue').hide();

$(#ok).click(function())
{
var ImageUrl1;
if ($(newValue).val() != $(oldValue).val())  
    $post(.....)
});

</script>


<div class="oldValue">@Model.ImageUrl1</div>
<div class="newValue">........</div>

<button id="ok">ok</button>

答案 3 :(得分:0)

虽然有一些选择,但没有本地方法可以做到这一点。因为你没有告诉我们你正在使用哪个持久性框架(例如,linq2sql,lightspeed,亚力学等等),我们不能说是否存在来自 框架的本地方式。

  1. 将起始模型序列化为表单字段。一个服务器端反序列化它并将其与MVC从POST给出的模型进行比较。我通常使用Newtonsoft.Json和UrlEncode。

  2. 对于每个模型字段,添加<input name="field_original" value="....">,然后在服务器端逐个比较它们,例如Model.Name == Form["name_original"]

  3. 使用jQuery跟踪输入是否已更改,并将其另存为隐藏输入。例如。 if (Form["name_modified"] == "true")) { _save name_ }

  4. 使用jQuery做一些其他花哨的跟踪系统。有太多的选择。例如,您可以使用原始值为每个输入添加“data-originalValue”属性。然后在表单提交之前,您可以检查每个项目,并使用更改的属性的名称更新另一个<input>

  5. 从数据存储中获取模型所基于的原始实体。手动检查每个字段,并仅更新已更改的字段。

  6. 如果您的持久层支持更改跟踪(如EF)

    1. 获取原始实体
    2. 使用模型
    3. 中的值更新实体中的值
    4. 确保设置与现有相同的值不会将属性标记为已更改
    5. 保存实体(它应该只保存已修改的字段)
  7. 上面#1的例子

    <form ...>
        <input type="hidden" name="OldModel" value="@Url.Encode(JsonConvert.SerializeObject(Model))"/>
        <!-- the rest of  your model fields --!>
        @Html.TextBoxFor(m => m.Url)
    
    控制器方法
    using Newtonsoft.Json;
    
    [HttpPost]
    public ActionResult Save(MyModel model) {
        var oldModel = JsonConvert.DeserializeObject<MyModel>(
                            HttpUtility.UrlDecode(Request.Form["OldModel"]));
        if (oldModel.Url != model.Url) { 
            // code to save the Url field only
        }
    }