【问题标题】:How to return 404 page in ASP .NET MVC when query string parameters is incorrect查询字符串参数不正确时如何在 ASP .NET MVC 中返回 404 页面
【发布时间】:2013-08-19 15:03:24
【问题描述】:

假设我有以下操作

public ViewResult Products(string color)
{...}

以及将 url “产品”映射到此操作的路由。

根据 SEO 提示链接 /products?color=red 应该返回

200 正常

但是链接/products?someOtherParametr=someValue

404 未找到

所以问题是——在这种情况下如何处理不存在的查询参数并返回 404

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-4


    【解决方案1】:

    考虑到What is the proper way to send an HTTP 404 response from an ASP.NET MVC action? 接受的答案,有一个特殊的ActionResult 可以满足您的期望。

    public class HomeController : Controller
    {
        public ViewResult Products(string color)
        {
            if (color != "something") // it can be replaced with any guarded clause(s)
                return new HttpNotFoundResult("The color does not exist.");
            ...
        }
    }
    

    更新:

    public class HomeController : Controller
    {
        public ViewResult Products(string color)
        {
            if (Request.QueryString.Count != 1 || 
                Request.QueryString.GetKey(0) != "color")
                return new HttpNotFoundResult("the error message");
            ...
        }
    }
    

    【讨论】:

    • 我写的是关于 url /products?someOtherParametr=someValue 而不是 /products?color=something
    • 我在答案中写道,“它可以用任何受保护的条款替换”;因此,您可以通过检查 QueryString 对象来检查是否提供了适当的参数。这很简单。要我更新答案吗?
    • 是的,请。将不胜感激
    • 谢谢,但我找到了更灵活的方法
    • 我一直在寻找像这样简单的东西 - 从来不知道它存在。谢谢。
    【解决方案2】:

    在执行动作方法之前验证它。此方法对您项目的所有 Controller 或特定 Action 方法均有效。

    控制器动作方法

    [attr]  // Before executing any Action Method, Action Filter will execute to 
            //check for Valid Query Strings.
    public class ActionResultTypesController : Controller
    {
        [HttpGet]
        public ActionResult Index(int Param = 0)
        {
            return View();
        }
    
        [HttpPost]
        public ActionResult Index(MyViewModel obj)
        {
            return View(obj);
        }
    
    }
    

    动作过滤器

    public class attr : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.ActionParameters.Count == 0 &&
                      System.Web.HttpContext.Current.Request.QueryString.Count > 0)
            {
                  //When no Action Parameter exists and Query String exists. 
            }
            else
            {
                // Check the Query String Key name and compare it with the Action 
                // Parameter name
                foreach (var item in System.Web.HttpContext
                                           .Current
                                           .Request.QueryString.Keys)
                {
                    if (!filterContext.ActionParameters.Keys.Contains(item))
                    {
                        // When the Query String is not matching with the Action 
                        // Parameter
                    }
                }
            }
            base.OnActionExecuting(filterContext);
        }
    }
    

    如果你注意上面的代码,我们正在检查 Action 参数,如下图所示。

    What can we do in case the QueryString passed does not exists in the Action Method Parameter? We can redirect the user to another page as shown in this link.

    filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
                            {
                                {"action", "ActionName"},
                                {"controller", "ControllerName"},
                                {"area", "Area Name"},
                                {"Parameter Name","Parameter Value"}
                            });
    

    或者

    我们可以这样做。下面提到的代码将写在OnActionExecuting Method Override

    filterContext.Result = new HttpStatusCodeResult(404);
    

    【讨论】:

    • 工作正常,但是当我们在动作参数中有复杂对象时会遇到麻烦
    • 你能举个例子吗?
    【解决方案3】:
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var actionParameters = filterContext.ActionParameters.Keys;
        var queryParameters = filterContext
                                      .RequestContext
                                      .HttpContext
                                      .Request
                                      .QueryString
                                      .Keys;
    
        // if we pass to action any query string parameter which doesn't 
        // exists in action we should return 404 status code
    
        if(queryParameters.Cast<object>().Any(queryParameter 
                                     => !actionParameters.Contains(queryParameter)))
            filterContext.Result = new HttpStatusCodeResult(404);
    }
    

    其实,如果你不想在每个控制器中都写 this is,你应该重写 DefaultControllerFactory

    【讨论】:

      【解决方案4】:

      这适用于 Asp.Net Core。 在 Controller ActionMethods 中使用下面的一行代码:

      return StatusCode(404, "Not a valid request.");
      

      在 OnActionExecuting 方法中,将 StatusCode 设置为 context.Result,如下例所示:

      public override void OnActionExecuting(ActionExecutingContext context)
      {
          string color = HttpContext.Request?.Query["color"].ToString();
          if (string.IsNullOrWhiteSpace(color))
          {
              // invalid or no color param, return 404 status code
              context.Result = StatusCode(200, "Not a valid request.");
          }
          else
          {
              // write logic for any common functionality
          }
          base.OnActionExecuting(context);
      }
      

      【讨论】:

        猜你喜欢
        • 2016-10-07
        • 1970-01-01
        • 1970-01-01
        • 2014-03-27
        • 2020-09-27
        • 2018-05-08
        • 1970-01-01
        • 2022-11-16
        • 1970-01-01
        相关资源
        最近更新 更多