ASP.NET MVC5 Controller Action只能使用RedirectToAction访问

时间:2015-03-23 09:33:18

标签: c# asp.net asp.net-mvc-5

我正在尝试创建用户注册序列。为此,控制器中的每个方法都使用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,
    });
}

1 个答案:

答案 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);