使用 OwinSelfHost自承载 AspNet WebApi

文章目录

  • 前言
  • 二、使用步骤
    • 1. 创建项目
    • 2. 添加相关的 Nuget
    • 3. 添加控制器
    • 4. 添加一个 Setup 类
    • 5. Autofac 集成
    • 6.Swagger 集成
    • 7. AutoMapper 集成
    • 8. 改造 Program
    • 9. 添加对 Windows 服务支持
    • 10. 补充
  • 总结


前言

为何要写这篇文章?
最初是一个很常规的WebApiece项目基于 .net framework 4.7.2, 调试时部署在本地IIS
测试完成后需要部署到服务器上, 不想再配IIS(由于之前有多个.netcore项目都是托管在Windows服务中), 多以就找找了相关的资料,决定使用相似的方式来改造以下.

OwinSelfHost 资料


二、使用步骤

1. 创建项目

添加一个基于Framework 4.7.2的控制台应用
使用 OwinSelfHost自承载 AspNet WebApi_第1张图片

2. 添加相关的 Nuget

  1. Autofac.WebApi2
  2. AutoMapper
  3. log4net
  4. Microsoft.AspNet.WebApi.Client
  5. Microsoft.AspNet.WebApi.OwinSelfHost
  6. Swashbuckle

3. 添加控制器

添加项目文件夹 Controllers
添加一个控制器, 代码如下

    [RoutePrefix("api/consumer")]
    public class ConsumerController : ApiControllerBase
    {
        private readonly ILog _log;
        /// 
        /// 实例化一个对象
        /// 
        public ConsumerController(ILog log) // 使用autofac作为依赖注入容器,集成方式后面会有介绍
        {
            _log = log ?? throw new ArgumentNullException(nameof(log));
        }

		[HttpPost]
        [Route("create")]
        public async Task<IHttpActionResult> CreateConsumerAsync([FromBody] ConsumerInfoCreateDto consumer)
        {   
        	// 这里有用到 AutoMapper, 集成方式后面会有介绍
	        try
            {
        		....
        		return Ok();
			}
			catch (Exception ex)
            {
                _log.Error("consumer-create", ex);
                return BadRequest(ex.InnerException == null ? ex.Message : ex.InnerException.Message);
            }
        }
	}

4. 添加一个 Setup 类

代码如下(示例):

    public class Startup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            var config = new HttpConfiguration();
            // Web API 路由
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            appBuilder.UseWebApi(config);
        }
	}

5. Autofac 集成

Setup 中添加如下代码:

        /// 
        /// Autofac 配置
        /// 
        /// 
        private static void ConfigureAutofac(HttpConfiguration config)
        {
            var builder = new ContainerBuilder();
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
            builder.ComponentRegistryBuilder.Registered += (sender, args) =>
            {
                args.ComponentRegistration.PipelineBuilding += (o, pipelineBuilder) =>
                {
                    pipelineBuilder.Use(new Log4NetMiddleware());
                };
            };
            builder.RegisterWebApiFilterProvider(config);
            builder.RegisterWebApiModelBinderProvider();
            var container = builder.Build();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        }

在 Configuration 方法中添加如下代码:

public void Configuration(IAppBuilder appBuilder)
{
	......
	ConfigureAutofac(config);
	......
}

Log4net 集成
以中间件的方式将Log4net添加到autofac中
相关代码:

public class Log4NetMiddleware : IResolveMiddleware
    {
        /// 
        /// 
        /// 
        /// 
        /// 
        public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
        {
            context.ChangeParameters(context.Parameters.Union(
                new[]
                {
                    new ResolvedParameter(
                        (p, i) => p.ParameterType == typeof(ILog),
                        (p, i) => LogManager.GetLogger(p.Member.DeclaringType)
                    ),
                }));

            // Continue the resolve.
            next(context);

            if (context.NewInstanceActivated)
            {
                var instanceType = context.Instance.GetType();

                var properties = instanceType
                    .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                    .Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);

                foreach (var propToSet in properties)
                {
                    propToSet.SetValue(context.Instance, LogManager.GetLogger(instanceType), null);
                }
            }
        }

        /// 
        /// 
        /// 
        public PipelinePhase Phase => PipelinePhase.ParameterSelection;
    }

Log4net 配置文件


<configuration>
  <configSections>
    
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
    
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  configSections>
  <log4net>
    .......
  log4net>
configuration>

这里很重要 ! ! ! 在AssemblyInfo 中添加 [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "config", Watch = true)]

6.Swagger 集成

Setup 中添加如下代码:

private static void ConfigureSwagger(HttpConfiguration config)
{
	var thisAssembly = typeof(Startup).Assembly;
	var parentPath = Path.GetDirectoryName(thisAssembly.Location);
	config.EnableSwagger(action =>
	{
		action.SingleApiVersion("v1", "swagger doc");
		action.IncludeXmlComments($@"{parentPath}\xxxxx.xml");
	}).EnableSwaggerUi(action =>
	{
		action.DocumentTitle("title");
	});
}

在 Configuration 方法中添加如下代码:

public void Configuration(IAppBuilder appBuilder)
{
	......
	ConfigureSwagger(config);
	......
}

7. AutoMapper 集成

添加 AutoMapper 配置类, 代码如下:

public static class AutoMapperConfig
{
	public static IMapper Mapper { get; private set; }       
	public static void Configure()
	{
		var config = new MapperConfiguration(cfg =>
		{
			#region consumer info
			cfg.CreateMap<ConsumerInfoCreateDto, ConsumerInfo>();
			cfg.CreateMap<ConsumerInfo, ConsumerInfoDto>();
			#endregion
		});
		Mapper = config.CreateMapper();
	}
}

在 Configuration 方法中添加如下代码:

public void Configuration(IAppBuilder appBuilder)
{
	......
	AutoMapperConfig.Configure();
	......
}

在 Controller 中通过以下方式使用:

AutoMapperConfig.Mapper.Map<ConsumerInfo>(consumer)

8. 改造 Program

代码如下:

static void Main(string[] args)
{
	var baseUri = "http://localhost:xxxx";
	WebApp.Start<Startup>(url: baseUri);
	Console.ReadLine();// 
}

到这里基本上已经可以了

9. 添加对 Windows 服务支持

创建Windows 服务 可借助 sc 相关的命令, 使用 OwinSelfHost自承载 AspNet WebApi_第2张图片
目前为止, 如果使用sc来创建服务,创建的服务是启动不了的.
添加一个继承自 ServiceBase 的类
代码如下:

public class WinService : ServiceBase
{
	protected override void OnStart(string[] args)
	{
		var baseUri = "http://localhost:xxxx";
		WebApp.Start<Startup>(url: baseUri);
	}
}

改造 Program

static void Main(string[] args)
{
	var ServiceCollections = new ServiceBase[]
	{
		new WinService()
	};
	ServiceBase.Run(ServiceCollections);
}

10. 补充

解决跨域

添加 Nuget Microsoft.AspNet.Cors

修改Configuration

public void Configuration(IAppBuilder appBuilder)
{
	......
	config.EnableCors(new EnableCorsAttribute("*", "*", "*"));// 允许所有
	......
}

总结

好了,就到这吧 ༼ つ ◕_◕ ༽つ

你可能感兴趣的:(Windows,服务,OwinSelfHost,WebApi,asp.net,c#,后端)