MVC控制器操作应该只处理某些参数值,否则为

时间:2016-03-21 15:13:20

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

我有一个带有一个参数的MVC控制器操作,该参数只能使用该参数的某些值调用(null / empty和一些特定的字符串),在其他情况下不应该被命中(主要是404)。我尝试过使用下面的RegexRouteConstraint。但这并不会过滤特定的字符串。

var route = new Route("{soortAanbod}", new MvcRouteHandler())
{
    Defaults = new RouteValueDictionary(new { controller = "Homepage", action = "Index", soortAanbod = UrlParameter.Optional }),
    Constraints = new RouteValueDictionary(new { soortAanbod = new RegexRouteConstraint("a|b|c|d|e") }),
    DataTokens = new RouteValueDictionary { { "area", context.AreaName } }
};
context.Routes.Add("Homepage_soortAanbod", route);

控制器如下所示:public ActionResult Index(string soortAanbod)

我也尝试使用动作过滤器,但这会混淆其他其他过滤器。如何使此路由仅匹配soortAanbod的指定值?

3 个答案:

答案 0 :(得分:1)

我认为您可以尝试属性路由,也可以编写自己的属性来检查params或重定向到某个地方。

public class SomeAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var yourstring = filterContext.RequestContext.HttpContext.Request.QueryString["string"];
        if (!string.IsNullOrWhiteSpace(yourstring))
        {
            if (yourstring is not ok) 
            filterContext.Result =
                new RedirectToRouteResult(
                    new RouteValueDictionary
                    {
                        {"controller", "SomeCtrl"},
                        {"action", "SomeAction"}
                    });
        }
        base.OnActionExecuting(filterContext);

    }

答案 1 :(得分:1)

您可以创建自定义约束并使用属性路由,在那里使用自定义约束并使约束构造函数接受您要避免的字符串列表

Custom MVC Route Constraint

Custom Constraint with Attribute Routing

答案 2 :(得分:1)

你有两个问题:

  1. 您的RegEx不包含anchors^$)来分隔您尝试匹配的字符串。因此,它匹配包含任何字母的任何字符串。
  2. 您的网址始终与默认路由匹配,因此即使您的自定义路由不匹配,您仍会访问该网页。默认路由将匹配任何 URL,即长度分别为0,1,2或3个段。
  3. 您可以通过删除自定义路线并使用IgnoreRoute(幕后使用StopRoutingHandler)来阻止这些特定网址进行匹配来解决此问题。

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            routes.IgnoreRoute("Homepage/Index/{soortAanbod}", 
                new { soortAanbod = new NegativeRegexRouteConstraint(@"^a$|^b$|^c$|^d$|^e$") });
    
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
    
    但是,有一点需要注意。 RegEx是not very good at doing negative matches,所以如果您不是RegEx大师,最简单的解决方案是构建NegativeRegexRouteConstraint来处理这种情况。

    public class NegativeRegexRouteConstraint : IRouteConstraint
    {
        private readonly string _pattern;
        private readonly Regex _regex;
    
        public NegativeRegexRouteConstraint(string pattern)
        {
            _pattern = pattern;
            _regex = new Regex(pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled);
        }
    
        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            if (parameterName == null)
                throw new ArgumentNullException("parameterName");
            if (values == null)
                throw new ArgumentNullException("values");
    
            object value;
            if (values.TryGetValue(parameterName, out value) && value != null)
            {
                string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
                return !_regex.IsMatch(valueString);
            }
            return true;
        }
    }