欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET MVC 控制器

程序员文章站 2022-07-09 21:56:55
上篇我们说到。编写控制器类的步骤可总结为两个:实现一个类,然后在该类中添加一些公有方法,在运行的该类的时候可作为控制器发现,而这些方法则作为操作被发现。 这里我们有两个细节: 1:系统如何知道实例化那个控制器 2:如何确定用那个方法。 路由: 1:被传统的路由发现,2:通过特性路由发现,3:通过混合 ......

  上篇我们说到。编写控制器类的步骤可总结为两个:实现一个类,然后在该类中添加一些公有方法,在运行的该类的时候可作为控制器发现,而这些方法则作为操作被发现。

这里我们有两个细节:

1:系统如何知道实例化那个控制器

2:如何确定用那个方法。

  路由:

1:被传统的路由发现,2:通过特性路由发现,3:通过混合路由策略发现,

传统路由不做过多解释。特性路由,可以让url模版与处理请求时使用的控制器和操作保持独立,以后,即使url进行修改,也不需要重构代码。

混合路由则时前两者一起使用,不过注意的是,特性定义的路由比传统路由的优先级更高。

  poco(plain old c# object)

控制器类可以是一个普通的传统c#对象。如果想被发现,要么类名带有controller后缀,要么用controller特性修饰该类。poco简单来说,它能减少开销和/内存占用量。

 

  访问http上下文

  poco最大的问题是没有http上下文,那么我们可以通过actioncontext来实现如:

public class pococontroller
{
    [actioncontroller]
    public actioncontext context{get;set}
......  
}

  操作筛选器

 1:它是围绕做方法运行的一段代码,可用于修改和扩展方法本身的行为。

public interface iactionfilter
{
   void onactionexecuting(actionexecutingcontext filtercontext);
   void onactionexected(actionexecutedcontext filtercontext);      
}

  它提供了挂钩,在操作之前和之后运行代码。在筛选器内能够访问请求和控制器上下文,并且可以读取和修改参数。

每个继承了cobtroller类的,用户定义的控制器都会获得iactionfilter接口的默认实现。,事实上,基类controller提供了一对可重写的方法,onactionexecuting和onactionexecuted。这就代表每个控制器类都有一个机会,用来决定在调用给定方法前,后或者调用方法前后做些什么,只需要重写基类的方法就能实现这种功能。当然poco不具备.

  

 protected datetime starttime;
        public override void onactionexecuting(actionexecutingcontext context)
        {
            var action = context.actiondescriptor.routevalues["action"];
            if(string.equals(action,"index",stringcomparison.currentcultureignorecase))
            {
                starttime = datetime.now;
            }
            base.onactionexecuting(context);
        }
        public override void onactionexecuted(actionexecutedcontext context)
        {
            var action = context.actiondescriptor.routevalues["action"];
            if (string.equals(action, "index", stringcomparison.currentcultureignorecase))
            {
                var timespan = datetime.now-starttime;
                context.httpcontext.response.headers.add(
                "duration", timespan.totalmilliseconds.tostring());
                
            }
            base.onactionexecuted(context);
        }

  ASP.NET MVC 控制器

 

 计算执行了多少毫秒

2:筛选器的分类

:操作筛选器只是asp.net core 管道中调用的一种筛选器,按照筛选器实际完成的额任务,可分成不同的类型。

 

类型 描述
授权筛选器 管道中运行的第一个类筛选器,用来确定发出请求的用户是否有权发出当前的请求
资源筛选器 当授权之后,在管道的其余部分之前以及管道组件之后运行,对于缓存很有用
操作筛选器 在控制器方法操作之前和之后运行
异常筛选器 如果注册,则在发生未处理异常时触发
结果筛选器 在操作方法结果之前和之后运行

可以将筛选器应用单独方法,也可以应用到整个控制器类,影响该控制器公开的所有操作方法,相对的,在应用程序启动时注册了全局筛选器之后,他们将自动应用到任何控制器类的任何操作。

①:添加自定义头

 public class headerattribute:actionfilterattribute
    {
        public string name { get; set; }
        public string value { get; set; }
        public override void onactionexecuted(actionexecutedcontext context)
        {
           if(!string.isnullorwhitespace(name)&&!string.isnullorwhitespace(value))
            {
                context.httpcontext.response.headers.add(name, value);
            }
            return;
        }
        
    }

② 设置请求的区域性

 [attributeusage(attributetargets.class|attributetargets.method,allowmultiple =false)]
    public class cultureattribute:actionfilterattribute
    {
        public string name { get; set; }
        public static string cookiename { get { return "_culture"; } }
        public override void onactionexecuting(actionexecutingcontext context)
        {
            var culture = name;
            if (string.isnullorwhitespace(culture))
                culture = getsavedcultureordefault(context.httpcontext.request);

            setcultureonthread(culture);
            base.onactionexecuting(context);
        }

        private  static void setcultureonthread(string language)
        {
            var cultureinfo = new cultureinfo(language);
            cultureinfo.currentculture = cultureinfo;
            cultureinfo.currentuiculture = cultureinfo;
        }

        private static string getsavedcultureordefault(httprequest request)
        {
            var culture = cultureinfo.currentculture.name;
            var cookie = request.cookies[cookiename] ?? culture;
            return culture;
        }
    }

主要是在操作方法之前检查一个名为_culture的自定义cookie,其中包含了用户首选的语言,如果没找到cookie,筛选器默认使用当前区域性,并赋值给当前的线程。最后全局注册

③:将方法限制只能ajax调用

   public class ajaxonlyattribute:actionmethodselectorattribute
    {
        public override bool isvalidforrequest(routecontext routecontext, actiondescriptor action) => routecontext.httpcontext.request.isajaxrequest();

    }
public static class httprequestextensions
    {
        public static bool isajaxrequest(this httprequest httprequest)
        {
            if (httprequest == null)
                throw new argumentexception("request");
            if (httprequest.headers != null)
                return httprequest.headers["x-requested-with"] == "xmlhttprequest";
            return false;
        }
    }