当前位置: 移动技术网 > IT编程>开发语言>.net > .NET Core开发日志——Filter

.NET Core开发日志——Filter

2018年08月26日  | 移动技术网IT编程  | 我要评论

许昌招聘,小学语文教学设计,汽车涂料

asp.net core mvc中的filter作用是在请求处理管道的某些阶段之前或之后可以运行特定的代码。

filter特性在之前的asp.net mvc中已经出现,但过去只有authorization,exception,action,result四种类型,现在又增加了一种resource类型。所以共计五种。

resource类型filter在authorization类型filter之后执行,但又在其它类型的filter之前。且执行顺序也在model binding之前,所以可以对model binding产生影响。

asp.net core mvc框架中可以看到有consumesattribute及formatfilter两种实现iresourcefilter接口的类。

consumesattribute会按请求中的content-type(内容类型)进行过滤,而formatfilter能对路由或路径中设置了format值的请求作过滤。

一旦不符合要求,就对resourceexecutingcontext的result属性设置,这样可以达到短路效果,阻止进行下面的处理。

consumesattribute类的例子:

public void onresourceexecuting(resourceexecutingcontext context)
{
    ...

    // only execute if the current filter is the one which is closest to the action.
    // ignore all other filters. this is to ensure we have a overriding behavior.
    if (isapplicable(context.actiondescriptor))
    {
        var requestcontenttype = context.httpcontext.request.contenttype;

        // confirm the request's content type is more specific than a media type this action supports e.g. ok
        // if client sent "text/plain" data and this action supports "text/*".
        if (requestcontenttype != null && !issubsetofanycontenttype(requestcontenttype))
        {
            context.result = new unsupportedmediatyperesult();
        }
    }
}

filter在asp.net core mvc里除了保留原有的包含同步方法的接口,现在又增加了包含异步方法的接口。

同步

  • iactionfilter
  • iauthorizationfilter
  • iexceptionfilter
  • iresourcefilter
  • iresultfilter

异步

  • iasyncactionfilter
  • iasyncauthorizationfilter
  • iasyncexceptionfilter
  • iasyncresourcefilter
  • iasyncresultfilter

新的接口不像旧有的接口包含两个同步方法,它们只有一个异步方法。但可以实现同样的功能。

public class sampleasyncactionfilter : iasyncactionfilter
{
    public async task onactionexecutionasync(
        actionexecutingcontext context,
        actionexecutiondelegate next)
    {
        // 在方法处理前执行一些操作
        var resultcontext = await next();
        // 在方法处理后再执行一些操作。
    }
}

attribute形式的filter,其构造方法里只能传入一些基本类型的值,例如字符串:

public class addheaderattribute : resultfilterattribute
{
    private readonly string _name;
    private readonly string _value;

    public addheaderattribute(string name, string value)
    {
        _name = name;
        _value = value;
    }

    public override void onresultexecuting(resultexecutingcontext context)
    {
        context.httpcontext.response.headers.add(
            _name, new string[] { _value });
        base.onresultexecuting(context);
    }
}


[addheader("author", "steve smith @ardalis")]
public class samplecontroller : controller

如果想要在其构造方法里引入其它类型的依赖,现在可以使用servicefilterattribute,typefilterattribute或者ifilterfactory方式。

servicefilterattribute需要在di容器中注册:

public class greetingservicefilter : iactionfilter
{
    private readonly igreetingservice greetingservice;

    public greetingservicefilter(igreetingservice greetingservice)
    {
        this.greetingservice = greetingservice;
    }

    public void onactionexecuting(actionexecutingcontext context)
    {
        context.actionarguments["param"] = 
            this.greetingservice.greet("james bond");
    }

    public void onactionexecuted(actionexecutedcontext context)
    { }
}


services.addscoped<greetingservicefilter>();


[servicefilter(typeof(greetingservicefilter))]
public iactionresult greetservice(string param)

typefilterattribute则没有必要:

public class greetingtypefilter : iactionfilter
{
    private readonly igreetingservice greetingservice;

    public greetingtypefilter(igreetingservice greetingservice)
    {
        this.greetingservice = greetingservice;
    }

    public void onactionexecuting(actionexecutingcontext context)
    {
        context.actionarguments["param"] = this.greetingservice.greet("dr. no");
    }

    public void onactionexecuted(actionexecutedcontext context)
    { }
}

[typefilter(typeof(greetingtypefilter))]
public iactionresult greettype1(string param)

ifilterfactory也是不需要的:

public class greetingfilterfactoryattribute : attribute, ifilterfactory
{
    public bool isreusable => false;

    public ifiltermetadata createinstance(iserviceprovider serviceprovider)
    {
        var logger = (igreetingservice)serviceprovider.getservice(typeof(igreetingservice));
        return new greetingfilter(logger);
    }

    private class greetingfilter : iactionfilter
    {
        private igreetingservice _greetingservice;
        public greetingfilter(igreetingservice greetingservice)
        {
            _greetingservice = greetingservice;
        }
        public void onactionexecuted(actionexecutedcontext context)
        {
        }

        public void onactionexecuting(actionexecutingcontext context)
        {
            context.actionarguments["param"] = _greetingservice.greet("dr. no");
        }
    }
    }

[greetingfilterfactory]
public iactionresult greettype1(string param)

filter有三种范围:

  • global
  • controller
  • action

后两种可以通过attribute的方式附加到特定action方法或者controller类之上。对于global,则要在configureservices方法内部添加。

public void configureservices(iservicecollection services)
{
    services.addmvc(options =>
    {
        // by instance
        options.filters.add(new adddeveloperresultfilter("tahir naushad"));

        // by type
        options.filters.add(typeof(greetdeveloperresultfilter)); 
    });

}

顾名思义,global将对所有controller及action产生影响。所以务必对其小心使用。

这三种范围的执行顺序在设计程序的时候也需要多作考虑:

  1. global范围的前置处理代码
  2. controller范围的前置处理代码
  3. action范围的前置处理代码
  4. action范围的后置处理代码
  5. controller范围的后置处理代码
  6. global范围的后置处理代码

典型的前置处理代码如常见的onactionexecuting方法,而常见的后置处理代码,则是像onactionexecuted方法这般的。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网