ASP.NET MVC - Is IsPostBack still here?

21
我知道,我知道,我知道。在MVC中使用webforms是不应该的,我完全同意。但是,发薪水的人现在不会批准我们网站完全转换为MVC。因此,我正在逐步采取措施,逐页将它们转换为MVC并添加新功能。
我的问题是如何从控制器访问IsPostBack属性?
编辑:进一步澄清,我的MVC主页面上有一个webform用户控件,可以启动postbacks。我试图区分这些postbacks和MVC post。目前,我打算检查请求表单键是否存在“__viewstate”键,并将其视为postback。

公共静态布尔型函数IsPostBack(this HttpRequestBase request){return __viewstate-something-something}可能是最接近的。但是,在MVC主页中放置Web表单用户控件可能会在未来的ASP.NET MVC版本中出现问题。 - bzlm
为什么我们不应该在MVC中使用Web Forms?我正在使用Web Forms。但我不是专业人士。除了Web Forms,我们还能用什么? - Agah Toruk
11个回答

51

如果还有人感兴趣,你可以像这样在MVC Action方法中测试POST请求:

if (Request.HttpMethod=="POST") { 

}

非常感谢您,这正是在MVC中需要执行的确切方法! - Sean Haddy
4
千万不要这样做。您的控制器代码应该按方法进行组织。您的HttpGet方法,即[HttpGet],应该与HttpPost方法完全分开。有很多原因,其中一个是可测试性,可读性等。请参见下面tvanfosson的答案。 - Adam Tuliper
1
在2012年仍然有用,为此加1。 - patel.milanb
6
你的意思是“不惜一切代价避免这个”吗?如果你需要一个JavaScript标记来确定是否执行脚本,难道没有其他方法吗? - Nick
1
-1:这不能区分后台回发和 AJAX 提交。 - Vivian River

15

没有IsPostBack,每个请求都是POST或GET(或其他HTTP动词)。您可以使用AcceptVerbsAttribute限制您的操作允许的HTTP动词,即您将永远不会看到来自不允许的动词的请求。例如,以下仅允许POST。

  [AcceptVerbs( HttpVerbs.Post )]
  [ValidateAntiForgeryToken]
  public ActionResult Update( int id )
  {
  }

如果您需要将同一个操作名称用于GET/POST两种请求类型,并且它们实际上执行不同的操作,那么您可以分别为它们提供不同的签名或使用ActionNameAttribute来为其中一个操作创建别名,以便方法可以具有不同的名称。

  [AcceptVerbs( HttpVerbs.Get)]
  public ActionResult List()
  {
  }

  [AcceptVerbs( HttpVerbs.Post )]
  [ValidateAntiForgeryToken]
  public ActionResult List( string filter, int page, int limit )
  {
  }

或者

  [ActionName( "List" )]
  [AcceptVerbs( HttpVerbs.Get)]
  public ActionResult ListDisplay()
  {
  }

  [AcceptVerbs( HttpVerbs.Post )]
  [ValidateAntiForgeryToken]
  public ActionResult List()
  {
  }

编辑:请注意,我已将防伪令牌验证添加到POST操作中。您真的应该使用它来防止跨站点脚本攻击


实际上,在混合使用MVC和WebForms页面时仍然存在后台提交。请参见我上面的编辑。 - chief7

11
你可以在 Razor 中使用这段代码。
@if(IsPost)
{
//dosomething
}
else
{
//do some other thing
}

4
我经常使用这个方法(在我的BaseController类中声明)
 protected bool IsPostBack()
 {
     bool isPost = string.Compare(Request.HttpMethod, "POST", 
        StringComparison.CurrentCultureIgnoreCase) == 0;
     if (Request.UrlReferrer == null) return false;

     bool isSameUrl = string.Compare(Request.Url.AbsolutePath, 
        Request.UrlReferrer.AbsolutePath, 
        StringComparison.CurrentCultureIgnoreCase) == 0;

     return isPost && isSameUrl;
 }

3

控制器不继承自System.Web.UI.Page。没有isPostback属性。


2
ASP.NET视图引擎的视图确实继承自Page。 - Mehrdad Afshari

2

对于Asp.net Core 2.x,您可以在HttpRequest上创建一个扩展方法。根据@ibirite的回答,可能是这样的:

最初的回答:

using System;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;

namespace MyApp
{
    public static class HttpRequestExtensions
    {
        public static bool IsPostBack(this HttpRequest request)
        {
            var currentUrl = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path, request.QueryString);
            var referrer = request.Headers["Referer"].FirstOrDefault();

            bool isPost = string.Compare(request.Method, "POST",
               StringComparison.CurrentCultureIgnoreCase) == 0;
            if (referrer == null) return false;

            bool isSameUrl = string.Compare(currentUrl,
               referrer,
               StringComparison.CurrentCultureIgnoreCase) == 0;

            return isPost && isSameUrl;
        }
    }
}


0

我不确定我是否正确理解了你的问题,但在控制器上,您将有一个处理来自浏览器的初始GET请求的操作,以及一个处理POST请求的第二个操作。

 [AcceptVerbs(HttpVerbs.Post)]
 public ActionResult Create(MyModel model)
 {...}

 public ActionResult Create()
 {...}

0
如果在MVC页面中有多个表单,您可以在表单内部添加一个具有有意义的ID的隐藏输入,并测试它是否具有值。这样一来,您就不需要分别处理两种情况(用于get和post)。
因此,在页面和表单内部:
 <input type="hidden" id="testForm" name="testForm" value="1"/>

在控制器中:

if (Request.Form["testForm"] != null)
        { 
        // ACTIONS FOR THE POSTED FORM
        }

希望能对你有所帮助!


0

MVC框架不支持Web表单中使用的经典postback和viewstate。因此,您无法访问IsPostBack。

我给您的建议是拥有两个分支:一个是当前网站,您可以在其中添加已知错误的补丁;另一个是从头开始构建新网站的分支。新功能应该在这个分支中实现。我假设您的大部分代码库可以在新网站中重复使用。

当新网站准备好后,将其投入生产。


0
为什么你要在控制器内获取那个值?不确定这是否能帮到你,但你仍然可以使用传统的 Request 对象来获取由表单提交的信息...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接