通过AJAX调用将“TimeStamp”变量从cshtml页面传递给控制器

时间:2016-06-28 17:12:28

标签: c# ajax asp.net-mvc entity-framework asp.net-mvc-5

我是MVC的EF新手。我需要在应用程序中实现并发检查。

我正在关注有关EF中并发处理的内置支持的MSDN帮助:http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application

但在我的情况下,我正在进行部分更新,所以我使用AJAX调用服务器端方法来执行此操作。在这个服务器端方法中,我需要实现并发检查。

按照教程我在代码中进行了必要的更改:

首先在我的数据库中创建了时间戳列:

ALTER TABLE dbo.Job
ADD RowVersion rowversion NULL;

在实体类中:

[Timestamp]
public byte[] RowVersion { get; set; }

在我的Mapping类中(使用流畅的api):

this.Property(t =>     
    t.RowVersion).HasColumnName("RowVersion").IsConcurrencyToken();

在我的视图模型类中:

[Timestamp]
public byte[] RowVersion { get; set; }

在我的视图文件中:

@Html.HiddenFor(x => x.RowVersion)
JS文件中的

(ajax调用):

function UpdateJobTransferStatus(jobTransferStatusId, newJobTransferSatusId, currentAction, statusName) {
    var hdnJobId = $("#JobId").val();
    //var hdnRowVersion = $("#RowVersion").val();
    var hdnAccountingId = $("#hdnAccountingSystemId").val();
    $.ajax(
           {
               type: "GET",
               url: ResolveUrl("~/Api/Job/UpdateJobTransferStatus"),
               dataType: "json",
               contentType: "application/json; charset=utf-8",
               data: { jobId: hdnJobId, currentAction: currentAction, jobTransferStatusId: newJobTransferSatusId, accountingSystemId: hdnAccountingId },//,rowVersion: hdnRowVersion },
               success: function (data) {
                   GetPreviousOrNextStatus(jobTransferStatusId, currentAction, statusName, hdnAccountingId);
               },
               error: function (result) {

               }
           });

}

最后在我的控制器中(在我的ajax调用上): 我根据MSDN(using System.Data.Entity.Infrastructure;

添加了命名空间
[System.Web.Http.HttpGet]
public HttpResponseMessage UpdateJobTransferStatus(int jobId, int currentAction,
    int jobTransferStatusId, short accountingSystemId, byte[] rowVersion)

在这里,我总是得到'null'的'byte[] rowVersion',无论我是否在AJAX调用中将该值作为参数发送(我在代码片段中留了注释,我粘贴在这里。)

我已经检查过,每次成功插入/更新执行时,列都会在DB中进行更新,并且视图模型在每次页面加载时从此DB获取此RowVersion列的最新值。

在MSDN示例中,他们已经提交了表单,但我正在使用AJAX调用,除了我试图保持每个方面都相同。

发送整个视图模型对象可能会为我完成这项工作,但我不需要整个对象来执行我的部分更新(虽然我没试过)。

如何将rowVersion传递给ajax电话?

1 个答案:

答案 0 :(得分:1)

您应该将其作为字符串发送并将其转换回服务器上的字节数组。这是因为HTML页面将其作为字符串存储在base64格式的input标签(隐藏类型)中。 c#侧的细微变化应该可以解决它。

查看:现有代码无需更改,传入HiddenForbyte[]的默认行为是将其转换为Base 64字符串

c#c​​ode

[System.Web.Http.HttpGet]
public HttpResponseMessage UpdateJobTransferStatus(int jobId, int currentAction, int jobTransferStatusId, short accountingSystemId, string rowVersion){
    var rowVersionBytes = System.Convert.FromBase64String(rowVersion); // convert to byte array
}

使用Javascript:

function UpdateJobTransferStatus(jobTransferStatusId, newJobTransferSatusId, currentAction, statusName) {
    var hdnJobId = $("#JobId").val();
    var hdnRowVersion = $("#RowVersion").val(); // this will be a string
    var hdnAccountingId = $("#hdnAccountingSystemId").val();
    $.ajax(
       {
           type: "GET",
           url: ResolveUrl("~/Api/Job/UpdateJobTransferStatus"),
           dataType: "json",
           contentType: "application/json; charset=utf-8",
           data: { jobId: hdnJobId, currentAction: currentAction, jobTransferStatusId: newJobTransferSatusId, accountingSystemId: hdnAccountingId, rowVersion: hdnRowVersion }
           success: function (data) {
               GetPreviousOrNextStatus(jobTransferStatusId, currentAction, statusName, hdnAccountingId);
           },
           error: function (result) {
           }
       });
}

最后,因为您实际上正在执行更新,这应该是HttpPost或HttpPut而不是HttpGet。

  • 仅在检索数据时才使用HttpGet,并且不会更改任何数据。
  • 当可以使用完全相同的预期结果多次调用相同的修改时,应使用HttpPut(这也称为幂等),这通常用于更新。
  • 当每次调用同一个调用会导致不同的结果(在服务器上或在响应中)时,应该使用HttpPost,这通常用于创建

我在你的sql中再看到一个错误,它可能会对现有数据造成意外问题。列RowVersion应标记为NOT NULL,即使在现有表上,当指定rowversion类型时,Sql Server将使用值填充所有现有记录。

ALTER TABLE dbo.Job
ADD RowVersion rowversion NOT NULL