c# - 在asp.net核心中发送带有防伪令牌的post ajax请求不要访问控制器方法
问题描述
不确定我的请求有什么问题,但显然控制器操作没有收到我的帖子。我想使用防伪令牌发布此表单,并且我还想使用 ajax 请求。出于这个原因,我没有使用包含防伪令牌的默认 aspnet 核心表单,而是使用了 html helper @Html.AntiforgeryToken()
。知道问题出在哪里吗?
@model RunViewModel
@{
ViewData["Title"] = "Run";
}
<h1 class="text-info">@ViewData["Title"]</h1>
<form id="run-form">
@Html.AntiForgeryToken()
<div class="form-group">
<label asp-for="InstanceName"></label>
<input asp-for="InstanceName" class="form-control" placeholder="Enter an instance name here..." />
</div>
<div class="form-group">
<label asp-for="DatabaseName"></label>
<input asp-for="DatabaseName" class="form-control" placeholder="Enter a database name here..." />
</div>
<div class="form-group">
<label asp-for="FolderPath"></label>
<input asp-for="FolderPath" class="form-control" />
</div>
<div class="col-3 offset-4">
<button type="submit" class="btn btn-primary">Run!</button>
</div>
</form>
@section Scripts {
<script>
$("#run-form").submit(function () {
var data = $('#run-form').serializeArray();
console.log(data);
alert($('input:hidden[name="__RequestVerificationToken"]').val());
$.ajax({
type: 'POST',
url: '/Run/Run',
contentType: 'application/json',
headers: { RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val() },
data: JSON.stringify(data),
success: function (data) {
if (data.status = "success") {
alert("Database has been updated !"); //TODO : Mettre un div vert avec un message à la place.
}
},
error: function () {
alert("An error occured 2!"); //TODO : Mettre un div rouge avec un message à la place.
}
});
//event.preventDefault();
});
</script>
}
控制器部分是:
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Run(string jsonObj)
{
//TODO : CHECK JSONOBJ
RunViewModel model = JsonSerializer.Deserialize<RunViewModel>(jsonObj);
try
{
//Call a service here...
}
catch (Exception ex)
{
//Renvoyer un message
}
return Json(model);
}
并且视图模型是:
public class RunViewModel
{
[Required]
[Display(Name="Instance name : ")]
public string InstanceName { get; set; }
[Required]
[Display(Name="Database name : ")]
public string DatabaseName { get; set; }
[Required]
[Display(Name="SQL folder path : ")]
public string FolderPath { get; set; }
/// <summary>
/// Liste ordonnée des fichiers, regroupés par version, à lancer sur la base de données suivant la version actuelle de la base de données.
/// </summary>
public IOrderedEnumerable<IGrouping<Version, string>> SqlFilesGroupedByVersion { get; set; }
}
解决方案
jqXHR.success()、jqXHR.error() 和 jqXHR.complete() 回调将在 jQuery 1.8 中被弃用。要为最终删除准备代码,请改用 jqXHR.done()、jqXHR.fail() 和 jqXHR.always()。
使用 ModelState Validation 验证您的模型
使用 OnClick 方法提交表单以避免 e.reeventDefault()。
我根据您的要求在下面给出一个完整的示例(请阅读所有内联评论)-
模型:-
public class RunViewModel
{
[Required]
[Display(Name = "Instance name : ")]
public string InstanceName { get; set; }
[Required]
[Display(Name = "Database name : ")]
public string DatabaseName { get; set; }
[Required]
[Display(Name = "SQL folder path : ")]
public string FolderPath { get; set; }
/// <summary>
/// Liste ordonnée des fichiers, regroupés par version, à lancer sur la base de données suivant la version actuelle de la base de données.
/// </summary>
public IOrderedEnumerable<IGrouping<Version, string>> SqlFilesGroupedByVersion { get; set; }
}
public class ValidationError
{
public string PropertyName { get; set; }
public string[] ErrorList { get; set; }
}
控制器:-
public class RunController : Controller
{
[HttpGet]
// GET: Run/Save
public ActionResult Save()
{
var model = new RunViewModel();
return View(model);
}
// POST: Run/Save
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(RunViewModel model)
{
var status = "Failed";
var massage = "";
try
{
//If modelstate validation need
if (!ModelState.IsValid)
{
return Json(new
{
status,
massage,
model,
errorList = GetModelStateErrors(ModelState).ToList()
});
}
else
{
//Write your code
status = "success";
massage = "Database has been updated !";
}
}
catch (Exception ex)
{
massage = ex.Message;
}
return Json(new
{
status,
massage,
});
}
public IEnumerable<ValidationError> GetModelStateErrors(ModelStateDictionary modelState)
{
var errors = (from m in modelState
where m.Value.Errors.Count() > 0
select
new ValidationError
{
PropertyName = m.Key,
ErrorList = (from msg in m.Value.Errors
select msg.ErrorMessage).ToArray()
})
.AsEnumerable();
return errors;
}
}
保存.cshtml:-
@model RunViewModel
@{
ViewData["Title"] = "Run";
}
<h1 class="text-info">@ViewData["Title"]</h1>
<style>
.field-validation-valid{
color:#FF0000;
}
</style>
<form id="run-form">
@Html.AntiForgeryToken()
<div class="form-group">
<label asp-for="InstanceName"></label>
<input asp-for="InstanceName" class="form-control" placeholder="Enter an instance name here..." />
<span asp-validation-for="InstanceName"></span>
</div>
<div class="form-group">
<label asp-for="DatabaseName"></label>
<input asp-for="DatabaseName" class="form-control" placeholder="Enter a database name here..." />
<span asp-validation-for="DatabaseName"></span>
</div>
<div class="form-group">
<label asp-for="FolderPath"></label>
<input asp-for="FolderPath" class="form-control" />
<span asp-validation-for="FolderPath"></span>
</div>
<div class="col-3 offset-4">
<button type="button" id="btnSubmin" class="btn btn-primary">Run!</button>
</div>
</form>
@section Scripts {
<script>
$("#btnSubmin").on("click", function () {
var valToken = $('input:hidden[name="__RequestVerificationToken"]').val();
var model = getFormData('run-form');
$.ajax({
type: 'POST',
url: '/Run/Save',
contentType: 'application/x-www-form-urlencoded',//set a Content-Type of application/json; charset=UTF-8 When Call API,application/x-www-form-urlencoded is the default contentType
headers: { RequestVerificationToken: valToken },
dataType: 'json',
data: model,//you need to pass json string
}).done(function (data) {
if (data.status === "success") {
alert("Database has been updated !"); //TODO : Mettre un div vert avec un message à la place.
} else {
displayValidationErrors(data.errorList);
}
}).fail(function (data) {
alert("An error occured 2!"); //TODO : Mettre un div rouge avec un message à la place.
});
/*
The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks will be deprecated in jQuery 1.8. To prepare your code for their eventual removal, use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.
*/
});
//Show Validation Message
function displayValidationErrors(errors) {
$.each(errors, function (idx, validationError) {
$("span[data-valmsg-for='" + validationError.propertyName + "']").text(validationError.errorList[0]);// if not working then captilized ex: errorList to ErrorList,propertyName to PropertyName
});
}
//Convert to Json From InputForm
function getFormData(formId) {
var $form = $("#" + formId);
var unindexed_array = $form.serializeArray();
var indexed_array = {};
$.map(unindexed_array, function (n, i) {
indexed_array[n['name']] = n['value'];
});
return indexed_array;
}
</script>
}
(经测试)
推荐阅读
- r - R中的空间聚类/采样
- azure - 使用 powershell 在 Azure 中创建自动化操作组
- php - phpstan 不通过 strip_tags
- node.js - 从 AWS ElasticBeanstalk node.js 到 AWS ElastiCache Redis 的连接超时
- sap-cloud-sdk - 无法使用其他 ID 创建联系人
- forms - 输入文本时如何更改 PDF 表单字段背景?
- node.js - 使用选项 ALLOW_FIELD_ADDITION 插入缺少字段的 BigQuery(来自 nodeJS)
- api - CKAN:如何使用 api 更新/创建资源的数据字典?
- php - File_get_contents():无法打开流:连接被拒绝
- python - 提取测试pyhon-selenium