“更新模型”仅更改了属性

本文关键字:属性 更新 模型 更新模型 | 更新日期: 2023-09-27 18:26:19

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

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

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

“更新模型”仅更改了属性

控制器只知道来自请求的值。为了可靠地确定发生了什么变化,您需要将接收到的模型与从控制器操作逻辑或业务层逻辑中的(repository/dao/dal/anything)获得的当前模型进行比较,只要这些模型更适合您的应用程序。

那么您可能需要某种形式的DTO模式。

例如,如果你想为"创建"answers"编辑"操作使用不同的表单,那么你会做出以下操作:

新形式的一个类:

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===>dto"逻辑的构造函数。您也可以在此处将显示属性放在属性上。

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

如果我正确理解您想要什么,您可以使用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>

虽然有一些选项,但没有本机方法可以做到这一点。因为您没有告诉我们您使用的是哪种持久性框架(ef、linq2sql、lightspeed、subsonic等),所以我们不能说是否有框架的原生方式。

  1. 将起始模型序列化为表单字段。在服务器端,对其进行反序列化,并将其与POST中MVC提供的模型进行比较。我通常使用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)

  7. 获取原始实体

  8. 使用模型中的值更新实体中的值

  9. 确保设置与现有值相同的值不会将属性标记为已更改

  10. 保存实体(应该只保存修改的字段)

###上面的#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
    }
}