Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC5控制器操作只能使用RedirectToAction访问_C#_Asp.net_Asp.net Mvc 5 - Fatal编程技术网

C# ASP.NET MVC5控制器操作只能使用RedirectToAction访问

C# ASP.NET MVC5控制器操作只能使用RedirectToAction访问,c#,asp.net,asp.net-mvc-5,C#,Asp.net,Asp.net Mvc 5,我正在尝试创建一个用户注册序列。为了实现这一点,控制器中的每个方法都使用RedirectToAction将流传递到下一个控制器方法。问题是,用户也可以手动键入URI并猜测id,以便为任何用户打开RegisterAdditionalDetails视图 不幸的是,[ChildActionOnly]属性也阻止了RedirectToAction调用视图,那么我是否可以使用另一个属性,或者这种方法完全错误,是否有更好的方法来实现这种“注册向导” 我提出的最好的解决方案是将提供的id参数与登录的用户id进行

我正在尝试创建一个用户注册序列。为了实现这一点,控制器中的每个方法都使用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,
    });
}
[HttpPost]
[异名]
[ValidateAntiForgeryToken]
公共异步任务CreateUser(CreateUserViewModel模型)
{
if(ModelState.IsValid)
{
var user=新应用程序用户
{
MemberSince=DateTime.Now,
用户名=model.UserName,
Email=model.Email,
Name=“”,
街道=”,
城市=”,
PostalCode=“”,
生日=新的日期时间(1980,1,1,0,0,0),
Sex=“未定义”
};
var result=await UserManager.CreateAsync(用户、模型、密码);
if(result.successed)
{
等待SignInManager.SignInAsync(用户,isPersistent:false,rememberBrowser:false);
返回RedirectToAction(“RegisterAdditionalDetails”,“Profile”,new{id=user.id});
}
加法器(结果);
}
//如果我们走到这一步,有些东西失败了,重新显示形式
返回视图(模型);
}
公共异步任务注册表附加详细信息(字符串id)
{
if(id==null | | User.Identity.GetUserId()!=id)
{
返回新的HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var user=await UserManager.FindByIdAsync(id);
if(user==null)
{
返回HttpNotFound();
}
返回视图(新的RegisterAdditionalDetailsViewModel()
{
Id=user.Id,
Name=user.Name,
街道=用户。街道,
城市=用户。城市,
PostalCode=user.PostalCode,
BirthDate=user.BirthDate,
性别=用户。性别,
});
}

如果不想公开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将尝试在视图文件夹中查找
CreateUser.cshtml
。您可以如上所述通过“viewName”参数指定“View”

它有点臭,但它能起作用(希望如此)

或者,您可以将
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);

如果用户自己破坏了网站也没关系。您不希望发生的是Web服务器对这种行为的任何影响。是的,如果我将[ChildActionOnly]属性放在RegisterAdditionalDetails方法上,这将按要求工作。太简单了!作为User.Identity.GetUserId()也是一件好事,即使我使登录同步,也不会设置它(但如果我首先登录,然后通过向导与登录的用户一步一步地登录,则会起作用)。谢谢。事实上,这在今天似乎不起作用。调用时出错:return wait RegisterAdditionalDetails(user.Id);错误:“传递到字典中的模型项的类型为'MyProject.Models.RegisterAdditionalDetailsViewModel',但此字典需要'MyProject.Models.CreateUserViewModel'类型的模型项。我用其他解释和代码编辑了我的答案。”。我希望它能满足您的需要。从POST操作返回视图可能会导致在数据库中插入相同的数据。使用POST-redirect-GET模式可以避免这种情况。