重定向后HttpPost到ReturnURL

我正在编写一个ASP.NET MVC 2.0应用程序,要求用户在对项目进行投标之前登录。 我正在使用actionfilter来确保用户已登录,如果没有,则将它们发送到登录页面并设置返回URL。 下面是我在动作filter中使用的代码。

if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { filterContext.Result = new RedirectResult(String.Concat("~/Account/LogOn","?ReturnUrl=",filterContext.HttpContext.Request.RawUrl)); return; } 

在我的登录控制器中,我validation用户凭据,然后将其签名并重定向到返回URL

 FormsAuth.SignIn(userName, rememberMe); if (!String.IsNullOrEmpty(returnUrl)) { return Redirect(returnUrl); } 

我的问题是,这将始终使用Get(HttpGet)请求,而我的原始提交是一个post(HttpPost),应该始终是一个post。 任何人都可以建议一种传递此URL的方法,包括HttpMethod或任何解决方法,以确保使用正确的HttpMethod?

没有简单的方法可以做到这一点。 我建议您将未经身份validation的用户重定向到登录页面,而不是在发布到某个URL时,而是在请求将POST到经过身份validation的URL的表单时。

如果您知道您向未经身份validation的用户提交的表单将POST到网站的经过身份validation的部分,那么请不要向他提供表单。 请求此表单时,只需重定向到登录页面进行身份validation,并在经过身份validation后重定向到原始表单。 这样,您将确保只有经过身份validation的用户才能POST到受保护资源。

就自动POST请求而言(机器人,Web服务……)将简单的401状态代码返回给不提供凭证的请求应该绰绰有余。

我想我明白为什么你希望身份validation仅在出价POST操作上。 出价需要登录,但任何未登录的用户都可以看到拍卖页面。 就像ebay / amazon等一样。在您需要基于用户的付款或操作之前,一切都是可见的。

如果Request.RequestTypePOST则可以将属性更改为将Request.UrlReferrer返回到登录页面。 然后,他们将被重定向到拍卖页面,并且一旦登录就可以再次点击出价。您甚至可以使用UrlReferrer传递某个字段(例如金额),以便您可以在金额字段到达时重新填充金额字段。拍卖页面。 您可以从Request.Form集合中获取该字段。

 // in usage... [RequireLogin(AdditionalFields="amount,someotherfield")] [HttpPost] public ActionResult Bid(.....) // the attribute class RequireLoginAttribute : ActionFilterAttribute { public string AdditionalFields { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { var returnUrl = filterContext.HttpContext.Request.RawUrl; if (filterContext.HttpContext.Request.RequestType == "POST") { returnUrl = filterContext.HttpContext.Request.UrlReferrer.PathAndQuery; // look for FORM values in request to append to the returnUrl // this can be helpful for a good user experience (remembering checkboxes/text fields etc) } filterContext.Result = new RedirectResult(String.Concat("~/Account/LogOn", "?ReturnUrl=", returnUrl)); return; } base.OnActionExecuting(filterContext); } } 

您可以编写两个具有相同名称的Controller方法,但一个用于get,另一个用于post,并记住TempData(或会话)中get方法中的ReturnUrl,然后在post请求到达时从TempData获取ReturnUrl:

代码可能如下所示:

  public ActionResult LogOn(string returnUrl) { if (!string.IsNullOrEmpty(returnUrl)) { TempData["ReturnUrl"] = returnUrl; } return View(); } [HttpPost] public ActionResult LogOn(LogOnModel model, FormCollection collecton) { if (ModelState.IsValid) { AuthenticationResult logonStatus = TransactionScriptFactory.GetTransactionScript() .LogOn(model.Email, model.Password); if (logonStatus.AuthResult == AuthResultEnum.Success) { FormsService.SignIn(logonStatus.User.UserId, logonStatus.User.NickName, false); object returnUrl = string.Empty; TempData.TryGetValue("ReturnUrl", out returnUrl); string returnUrlStr = returnUrl as string; if (!string.IsNullOrEmpty(returnUrlStr)) { return Redirect(returnUrlStr); } else { return RedirectToAction("Index", "Home"); } } 

……

当您第一次使用get动作到达页面时,它是绝对的,然后将数据发布到服务器。

我想你也可以从Request.UrlReferrer获取整个url。