传递'TimeStamp'变量通过AJAX调用从cshtml页面到控制器
本文关键字:cshtml 控制器 变量 TimeStamp 传递 AJAX 调用 | 更新日期: 2023-09-27 17:53:11
我是新来的EF在MVC。我需要在应用程序中实现并发检查。
我是按照MSDN帮助关于内置支持并发处理EF: 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调用服务器端方法来完成。在这个服务器端方法中,我需要实现并发性检查。
按照教程,我在代码中做了必要的修改:首先在DB中创建时间戳列:
ALTER TABLE dbo.Job
ADD RowVersion rowversion NULL;
在实体类:
[Timestamp]
public byte[] RowVersion { get; set; }
在我的Mapping类(使用fluent api):
this.Property(t =>
t.RowVersion).HasColumnName("RowVersion").IsConcurrencyToken();
在我的视图模型类:
[Timestamp]
public byte[] RowVersion { get; set; }
in my view file:
@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调用?
您应该将其作为字符串发送,并将其转换回服务器上的字节数组。这是因为HTML页面以base64格式将其作为字符串存储在input
标记(类型为hidden)中。在c#端做个小改动就可以解决这个问题。
视图:不需要改变你现有的代码,HiddenFor
的默认行为,当一个byte[]
被传入是转换为一个base64字符串
[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,这通常用于create
我在你的sql中看到一个错误,这可能会对现有数据产生意想不到的问题。列RowVersion
应该被标记为NOT NULL
,因为即使在现有表上,当指定rowversion
类型时,Sql Server也会用一个值填充所有现有记录。
ALTER TABLE dbo.Job
ADD RowVersion rowversion NOT NULL