我需要确定它是否是同一个客户端,因此在Controller的操作方法中,我将一个id放入视图模型中,稍后将发送给视图模型。当用户在浏览器中输入一些内容并提交时,包含用户输入的视图模型和控制器发送到视图的id应该被发送回控制器。但是,在这种情况下,在调试时,我发现发送回控制器的视图模型没有携带id。我错过了什么?
我想也许View会创建一个新的视图模型来加载用户的输入,但是id在旧的视图模型中。
@model MicroCommunity.Models.RegisterViewModel
@{
ViewBag.Title = "Register";
}
<h2>@ViewBag.Title.</h2>
@using (Html.BeginForm("Register", "Account", FormMethod.Post, new {@class = "form-horizontal", role = "form"}))
{
@Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<hr/>
@Html.ValidationSummary("", new {@class = "text-danger"})
<div class="form-group">
@Html.LabelFor(m => m.Name, new {@class = "col-md-2 control-label"})
<div class="col-md-10">
@Html.TextBoxFor(m => m.Name, new {@class = "form-control"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Department, new {@class = "col-md-2 control-label"})
<div class="col-md-10">
@Html.TextBoxFor(m => m.Department, new {@class = "form-control"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.EmployeeCardURL, new {@class = "col-md-2 control-label"})
<div class="col-md-10">
@Html.TextBoxFor(m => m.EmployeeCardURL, new {@class = "form-control"})
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Register"/>
</div>
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
以下是GET方法中代码的一部分:
// GET: /Account/Register
var registerViewModel = new RegisterViewModel() {OpenId = wechatUserAccessToken.openid};
return View(registerViewModel);
这里是POST:
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser
{
Openid =model.OpenId,
UserName = model.OpenId,
EmployeeCardURL = model.EmployeeCardURL,
Department = new Department() {Name = model.Department},
Name = model.Name
};
try
{
var result = await UserManager.CreateAsync(user, model.OpenId);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
// var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine(
"Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
答案 0 :(得分:3)
视图中的input
属性没有相应的OpenId
字段,因此您无法以某种方式将其自动发送到您的POST操作。因此,您可以考虑将其作为隐藏字段包含在内部您的Html.BeginForm
:
@Html.HiddenFor(x => x.OpenId)
ASP.NET MVC是无状态的。这意味着您在渲染视图时发送一个视图模型,但这并不能保证在您回发到另一个控制器操作时将获得相同的视图模型。
现在,有人说,你应该知道,通过使用这种方法,任何人都可以向你的POST控制器动作发送请求,并且伪造 OpenId
属性,无论他想要什么价值。如果您想确保此值未被篡改,您可以考虑从您在GET操作中执行的相同位置(通常是数据库或缓存层)中检索它。
所以在你的POST动作中:
string openId = wechatUserAccessToken.openid;
目前还不清楚这个wechatUserAccessToken
实例是什么,但是如果它在你的POST操作中不可用,那么你可以考虑在服务器的某个地方存储这个openid
值(在数据库中? )因此,您不需要将其作为隐藏字段包含在每个请求中,而是将其与当前登录的用户会话相关联。这将保证服务器上的值始终可用且未被篡改。