ASP.NET Core中使用自定义MVC过滤器属性的依赖注入

原文:ASP.NET Core中使用自定义MVC过滤器属性的依赖注入

  除了将自己的中间件添加到ASP.NET MVC Core应用程序管道之外,您还可以使用自定义MVC过滤器属性来控制响应,并有选择地将它们应用于整个控制器或控制器操作。

  ASP.NET Core中常用的MVC过滤器之一是  ExceptionFilterAttribute,用于处理Wep API应用程序中的错误响应。它很容易实现,开发人员和我在ASP.NET Core中使用MVC过滤器属性所面临的问题是访问Startup.cs类中注入的组件。这些通常是配置,环境或日志记录。

  通常依赖注入对象的一个??非常有用的用法,例如上面提到的IEnvironment,IConfiguration和ILogger <T>,是您正在实现的MVC过滤器属性的不同行为。根据这些值,您的属性行为可能会有所不同。例如,您不希望将错误详细信息和堆栈跟踪公开给Production Web API服务错误响应,尤其是在该服务端点是公共的情况下。您希望仅针对隔离的开发和登台环境执行此操作。

示例MVC过滤器属性#

  在一个自定义ExceptionFilterAttrubute类的简单示例中,我将向您演示如何在自定义属性中使用依赖注入对象。让我们从代码开始吧。

    public class ExceptionMessage
    {
        private object errorMessage;
        public string Message { get; private set; }
        public string Description { get; private set; }
        public IDictionary<string,string> ValidationErrors { get; private set;}
        public ExceptionMessage(ExceptionContext context)
        {
            if (context.ModelState != null && context.ModelState.Any(m => m.Value.Errors.Any()))
            {
                this.Message = "Model validation failed.";
                this.ValidationErrors = context.ModelState.Keys
                    .SelectMany(key => context.ModelState[key].Errors.ToDictionary(k => key, v => v.ErrorMessage))
                    .ToDictionary(k => k.Key, v => v.Value);
            }
            else
            {
                this.Message = context.Exception.Message;
                this.Description = context.Exception.StackTrace;
            }
        }
    }

由于本文重点不是错误消息结构,不过在Microsoft REST API准则 Github存储库中提供了一些错误消息准则,这些可能会给你带来帮助。

现在您的错误响应理想情况下是一条JSON消息,但是让我们将序列化留给应用程序的管道并返回一个ObjectResponse派生实例。为此我创建了ErrorObjectResult

using Microsoft.AspNetCore.Mvc;
using System.Net;

namespace CzarCms.Models
{
    public class ErrorObjectResult : ObjectResult
    {
        public ErrorObjectResult(object value, HttpStatusCode statusCode = HttpStatusCode.InternalServerError) : base(value)
        {
            StatusCode = (int)statusCode;
        }
    }
}

除了获取状态代码的构造函数(默认为500内部服务器错误)和ObjectResponse基础构造函数的对象之外,此类中没有什么特别之处。我们在本文中关注的核心组件是我们的自定义ExceptionFilterAttribute派生类。

public class ApiExceptionFilter : ExceptionFilterAttribute
    {
        public override void OnException(ExceptionContext context)
        {
            var errorMessage = new ExceptionMessage(context);
            if (context.ModelState.ErrorCount==0)
                context.Result = new ErrorObjectResult(errorMessage);
            else
                context.Result = new ErrorObjectResult(errorMessage,HttpStatusCode.BadRequest);
            base.OnException(context);
        }
    }

让我们用这个属性来装饰我们的控制器来处理它可能发生的错误。

// GET api/values
        [HttpGet]
        [ApiExceptionFilter]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

设置依赖注入#

  我们首先需要为我们要在Startup类的MVC过滤器属性中访问的这三个接口设置依赖注入。

    public class Startup
    {
        public IConfiguration Configuration { get; private set; }
        public IHostingEnvironment HostingEnvironment { get; private set; }

        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {
            Configuration = configuration;
            HostingEnvironment = env;
            ILogger Logger = new LoggerFactory()
                .AddConsole()
                .AddDebug()
                .CreateLogger(typeof(Program));
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IConfiguration>(new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile($"appsettings.{this.HostingEnvironment.EnvironmentName.ToLower()}.json")
                .Build());
            services.AddLogging();
            services.AddMvc();

            services.AddScoped<ApiExceptionFilter>();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();
            app.UseMvc();
        }
    }

您可以看到我们将ApiExceptionFilter添加为我们的DI的作用域服务。这是因为我们将在控制器上以不同的方式引用它,以便通过带有参数的新构造函数的依赖注入来初始化它。

我们已经在Startup类中的ConfigureServices方法中注入了我们的IEnvironment和ILogger,但我们无法在属性中访问它。如果我们使用IEnvironment和ILogger参数添加属性的构造函数,我们将得到编译错误,因为您无法使用[ApiExceptionFilter]装饰Controller / Action,因为它现在需要通过IEnvironment和ILogger接口实现。为此,我们使用带有属性ServiceFilter的控制器来装饰  它,它将我们的  ApiExceptionFilter类的类型作为构造函数参数。

[HttpGet]
[ServiceFilter(typeof(ApiExceptionFilter))]
public IEnumerable<string> Get()
{
  return new string[] { "value1", "value2" };
}

最后,我们必须更新MVC过滤器属性的构造函数以接受IEnvironment,IConfiguration和ILogger参数。

public class ApiExceptionFilter : ExceptionFilterAttribute
    {
        private ILogger<ApiExceptionFilter> logger;
        private IHostingEnvironment environment;
        private IConfiguration configuration;
        public ApiExceptionFilter(IHostingEnvironment environment, IConfiguration configuration, ILogger<ApiExceptionFilter> logger)
        {
            this.environment = environment;
            this.configuration = configuration;
            this.logger = logger;
        }
        public override void OnException(ExceptionContext context)
        {
            var errorMessage = new ExceptionMessage(context);
            if (context.ModelState.ErrorCount==0)
                context.Result = new ErrorObjectResult(errorMessage);
            else
                context.Result = new ErrorObjectResult(errorMessage,HttpStatusCode.BadRequest);
            base.OnException(context);
        }
    }

我们在自定义过滤器属性类中注入了IEnvironment和ILogger <T>。从Microsoft.AspNetCore.Mvc.Filters命名空间中的任何操作过滤器属性派生的任何类都可以使用相同的方法。

原文地址:https://www.cnblogs.com/lonelyxmas/p/12052098.html

时间: 2024-10-12 14:55:28

ASP.NET Core中使用自定义MVC过滤器属性的依赖注入的相关文章

ASP.NET Core中使用默认MVC路由

ASP.NET Core里Route这块的改动不大,只是一些用法上有了调整,提供了一些更加简洁的语法. 而对于自定义路由的支持当然也是没有问题的,这个功能应该是从MVC1.0版本就已经有这个功能. 先看看ASP.NET Core里面实现默认MVC路由的配置方式 通常情况下,在使用MVC项目的时候,默认的路由就足够了,就是常见的通过Controller和Action获取具体的方法的方式. 从一个最基本的项目开始,执行以下步骤,就可以使得项目支持MVC路由 1.创建一个空白的ASP.NET Core

ASP.NET Core中显示自定义错误页面

在 ASP.NET Core 中,默认情况下当发生500或404错误时,只返回http状态码,不返回任何内容,页面一片空白. 如果在 Startup.cs 的 Configure() 中加上 app.UseStatusCodePages(); ,500错误时依然是一片空白(不知为何对500错误不起作用),404错误时有所改观,页面会显示下面的文字: Status Code: 404; Not Found 如果我们想不管500还是404错误都显示友好的自定义错误页面,该如何实现呢?请看下面的分解.

.NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了

最近有个需求就是一个抽象仓储层接口方法需要SqlServer以及Oracle两种实现方式,为了灵活我在依赖注入的时候把这两种实现都给注入进了依赖注入容器中,但是在服务调用的时候总是获取到最后注入的那个方法的实现,这时候就在想能不能实现动态的选择使用哪种实现呢?如果可以的话那么我只需要在配置文件中进行相应的配置即可获取到正确的实现方法的调用,这样的话岂不快哉!今天我们就来一起探讨下实现这种需求的几种实现方式吧. 作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu

基于 ASP.NET Core 2.0 WebAPI 后台框架搭建(1) - 依赖注入三层框架搭建

概述 本文章描述如何搭建 ASP.NET Core 2.0 WebAPI 依赖注入三层架构,为什么要加入依赖,并不是为了提供程序性能,而是为了项目间解耦,项目之间能够更加独立. 微软爸爸官方说明文档:在 ASP.NET Core 依赖注入 全面理解 ASP.NET Core 依赖注入 步骤 1. 新建解决方案,添加一个ASP.NET Core WebApi应用 2. 添加四个.Net Core类库:Entity.BLL.DAL.Common 3. 按照以下截图进行解决方案布局 4. 添加DAL层

ASP.NET Core中的ActionFilter与DI

一.简介 前几篇文章都是讲ASP.NET Core MVC中的依赖注入(DI)与扩展点的,也许大家都发现在ASP.NET CORE中所有的组件都是通过依赖注入来扩展的,而且面向一组功能就会有一组接口或抽象工厂来扩展功能,就如IControllerActivator这样的功能点在上篇文章(查看.NET Core源代码通过Autofac实现依赖注入到Controller属性)中也提到了,今天我们主要介绍一个大类似的扩展点,ASP.NET Core MVC中为我们提供了新的机制为Action Filt

ASP.NET Core中Middleware的使用

ASP.NET 5中Middleware的基本用法 在ASP.NET 5里面引入了OWIN的概念,大致意思是将网站部署.服务器.中间组件以及应用分离开,这里提到的Middleware就是中间组件. 这里引用asp.net网站的介绍图 Middleware的作用有点类似于httpmodule,服务器接收到的请求都会传递到各个Middleware,多个Middleware形成一个处理管道. 由于不针对于特定的请求,所以Middleware的执行范围是在Application之外,这种模式很适合处理日

ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)

在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入,本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入. 约定: 1.仓储层接口都以“I”开头,以“Repository”结尾.仓储层实现都以“Repository”结尾. 2.服务层接口都以“I”开头,以“Service”结尾.服务层实现都以“Service”结尾. 接下来我们正式进入主题,在上一章的基础上我们再添加一个web项目TianYa.DotNetShare.Core

ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)

原文:ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用) 在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. PS:本章将主要采用构造函数注入的方式,下一章将继续分享如何使之能够同时支持属性注入的方式. 约定: 1.仓储层接口都以“I”开头,以“Repos

如何在ASP.NET Core中自定义Azure Storage File Provider

文章标题:如何在ASP.NET Core中自定义Azure Storage File Provider作者:Lamond Lu地址:https://www.cnblogs.com/lwqlun/p/10406566.html项目源代码: https://github.com/lamondlu/AzureFileProvider 背景# ASP.NET Core是一个扩展性非常高的框架,开发人员可以根据自己的需求扩展出想要的功能.File Provider是ASP.NET Core中的一个重要组件