我正在尝试创建用户注册序列。为此,控制器中的每个方法都使用RedirectToAction将流传递给下一个控制器方法。问题是用户也可以手动输入URI并猜测id以打开任何用户的RegisterAdditionalDetails视图。
不幸的是,[ChildActionOnly]属性也阻止RedirectToAction调用视图,所以我可以使用另一个属性,或者这种方法完全错误,是否有更好的方法来实现这种“注册向导”?
我提出的最佳解决方案是将提供的id参数与登录的用户ID进行比较(因为用户在第一步之后已登录),但仍然允许用户为自己打破向导流
相关控制器代码:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> CreateUser(CreateUserViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser
{
MemberSince = DateTime.Now,
UserName = model.UserName,
Email = model.Email,
Name = "",
Street = "",
City = "",
PostalCode = "",
BirthDate = new DateTime(1980, 1, 1, 0, 0, 0),
Sex = "Undefined"
};
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
return RedirectToAction("RegisterAdditionalDetails", "Profile", new { id = user.Id });
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
public async Task<ActionResult> RegisterAdditionalDetails(string id)
{
if (id == null || User.Identity.GetUserId() != id)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var user = await UserManager.FindByIdAsync(id);
if (user == null)
{
return HttpNotFound();
}
return View(new RegisterAdditionalDetailsViewModel()
{
Id = user.Id,
Name = user.Name,
Street = user.Street,
City = user.City,
PostalCode = user.PostalCode,
BirthDate = user.BirthDate,
Sex = user.Sex,
});
}
答案 0 :(得分:1)
如果您不想公开RegisterAdditionalDetails URL并且视图不那么复杂,只需替换
return RedirectToAction("RegisterAdditionalDetails", "Profile", new { id = user.Id });
这个
return await RegisterAdditionalDetails(user.Id);
<强> [编辑] 强>
哦,对不起,我忘记了MVC,而不是WebAPI。长话短说,只需修改RegisterAdditionalDetails方法的返回代码,如:
return View("RegisterAdditionalDetails", new RegisterAdditionalDetailsViewModel()
故事更长,ViewEngine将尝试通过RequestContext
中的控制器和操作名称查找适当的视图。在这种情况下,初始操作为CreateUser
,因此ViewEngine默认会尝试在Views文件夹中查找CreateUser.cshtml
。您可以按照上面的“viewName”参数指定“查看”。
它有点臭,但它有效(希望如此)。
或者您可以将RegisterAdditionalDetail
的逻辑分成另一个方法或服务,然后在CreateUser
方法中调用它,并返回带有返回值的视图,如下所示:
// in the CreateUser method,
// call separated logic
var viewModel = await GetRegisterAdditionalDetailsViewModelAsync(user.Id);
// and then return a view with specific viewName and model.
return View("RegisterAdditionalDetails", viewModel);