ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入

在正式进入主题之前我们来看下几个概念:

一、依赖倒置

依赖倒置是编程五大原则之一,即:

1、上层模块不应该依赖于下层模块,它们共同依赖于一个抽象。

2、抽象不能依赖于具体,具体依赖于抽象。

其中上层就是指使用者,下层就是指被使用者。

二、IoC控制反转

控制反转(IoC,全称Inversion of Control)是一种思想,所谓“控制反转”,就是反转获得依赖对象的过程。

三、依赖注入(DI)

依赖注入设计模式是一种在类及其依赖对象之间实现控制反转(IoC)思想的技术。

所谓依赖注入(DI,全称Dependency Injection),就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。

依赖注入主要分为3种:构造函数注入、属性注入、方法注入。

这里就不做过多的描述,如果有机会会通过具体例子再和大家分享,下面我们正式进入本章主题。

PS:ASP.NET Core 内置的IoC容器目前只支持构造函数注入,以下我们也主要讲解构造函数注入的方式。

话不多说,直入主题看我们的解决方案结构:

分别对上面的工程进行简单的说明:

1、TianYa.DotNetShare.Model:为demo的实体层

2、TianYa.DotNetShare.Repository:为demo的仓储层即数据访问层

3、TianYa.DotNetShare.Service:为demo的服务层即业务逻辑层

4、TianYa.DotNetShare.CommTool:为demo的公共工具类库

5、TianYa.DotNetShare.SharpCore:为demo的Sharp核心类库

6、TianYa.DotNetShare.CoreMvcDemo:为demo的web层项目,MVC框架

约定:

1、公共的类库,我们选择.NET Standard 2.0作为目标框架,可与Framework进行共享。

2、本demo的web项目为ASP.NET Core Web 应用程序(.NET Core 2.2) MVC框架。

一、实体层

1、新建一个学生实体 Student

using System;
using System.Collections.Generic;
using System.Text;

namespace TianYa.DotNetShare.Model
{
    /// <summary>
    /// 学生类
    /// </summary>
    public class Student
    {
        /// <summary>
        /// 学号
        /// </summary>
        public string StuNo { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 年龄
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        public string Sex { get; set; }
    }
}

demo中的实体就这样了

二、仓储层

本demo的仓储层需要引用我们的实体层TianYa.DotNetShare.Model

为什么选择用仓储,原因很简单,方便我们进行个性化扩展。在数据操作的底层进行其他个性化逻辑处理。

约定:

1、接口的定义放在根目录下,接口的实现类,统一放到Impl文件夹,表示实现类目录。

2、每个实体,对应一个仓储的接口和实现类,即有多少个实体,就对应创建多少个接口和实现类。

我们新建一个Student的仓储接口IStudentRepository.cs

using System;
using System.Collections.Generic;
using System.Text;

using TianYa.DotNetShare.Model;

namespace TianYa.DotNetShare.Repository
{
    /// <summary>
    /// 学生类仓储层接口
    /// </summary>
    public interface IStudentRepository
    {
        /// <summary>
        /// 根据学号获取学生信息
        /// </summary>
        /// <param name="stuNo">学号</param>
        /// <returns>学生信息</returns>
        Student GetStuInfo(string stuNo);
    }
}

接着在Impl中新建一个Student的仓储实现StudentRepository.cs

using System;
using System.Collections.Generic;
using System.Text;

using TianYa.DotNetShare.Model;

namespace TianYa.DotNetShare.Repository.Impl
{
    /// <summary>
    /// 学生类仓储层
    /// </summary>
    public class StudentRepository : IStudentRepository
    {
        /// <summary>
        /// 根据学号获取学生信息
        /// </summary>
        /// <param name="stuNo">学号</param>
        /// <returns>学生信息</returns>
        public Student GetStuInfo(string stuNo)
        {
            //数据访问逻辑,此处为了演示就简单些
            var student = new Student();
            switch (stuNo)
            {
                case "10000":
                    student = new Student() { StuNo = "10000", Name = "张三", Sex = "男", Age = 20 };
                    break;
                case "10001":
                    student = new Student() { StuNo = "10001", Name = "钱七七", Sex = "女", Age = 18 };
                    break;
                case "10002":
                    student = new Student() { StuNo = "10002", Name = "李四", Sex = "男", Age = 21 };
                    break;
                default:
                    student = new Student() { StuNo = "10003", Name = "王五", Sex = "男", Age = 25 };
                    break;
            }

            return student;
        }
    }
}

该类实现了IStudentRepository接口

三、服务层

本demo的服务层需要引用我们的实体层TianYa.DotNetShare.Model和我们的仓储层TianYa.DotNetShare.Repository

服务层与仓储层类似,它属于仓储层的使用者。定义的方式也与仓储层类似,有接口和Impl实现目录。

但服务层不需要一个实体对应一个,服务层更多的是按照功能模块进行划分,比如一个登录模块,创建一个LoginService。

为了演示,我们新建一个Student的服务层接口IStudentService.cs

using System;
using System.Collections.Generic;
using System.Text;

using TianYa.DotNetShare.Model;

namespace TianYa.DotNetShare.Service
{
    /// <summary>
    /// 学生类服务层接口
    /// </summary>
    public interface IStudentService
    {
        /// <summary>
        /// 根据学号获取学生信息
        /// </summary>
        /// <param name="stuNo">学号</param>
        /// <returns>学生信息</returns>
        Student GetStuInfo(string stuNo);
    }
}

接着我们同样在Impl中新建一个Student的服务层实现StudentService.cs

using System;
using System.Collections.Generic;
using System.Text;

using TianYa.DotNetShare.Model;
using TianYa.DotNetShare.Repository;

namespace TianYa.DotNetShare.Service.Impl
{
    /// <summary>
    /// 学生类服务层
    /// </summary>
    public class StudentService : IStudentService
    {
        /// <summary>
        /// 定义仓储层学生抽象类对象
        /// </summary>
        protected IStudentRepository StuRepository;

        /// <summary>
        /// 空构造函数
        /// </summary>
        public StudentService() { }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="stuRepository">仓储层学生抽象类对象</param>
        public StudentService(IStudentRepository stuRepository)
        {
            this.StuRepository = stuRepository;
        }

        /// <summary>
        /// 根据学号获取学生信息
        /// </summary>
        /// <param name="stuNo">学号</param>
        /// <returns>学生信息</returns>
        public Student GetStuInfo(string stuNo)
        {
            var stu = StuRepository.GetStuInfo(stuNo);
            return stu;
        }
    }
}

该类实现了IStudentService接口

四、公共工具类库

公共工具类库就是将来我们要在里面写各种各样的帮助类以提高程序的可复用性,此处就不做赘述。

五、Sharp核心类库

需要从NuGet上引用以下几个程序集:

Sharp核心类库为公共的基础类,最底层。

其中Model为实体目录,主要存放数据库连接相关的实体。Extensions为扩展目录,主要存放最底层的扩展类,我们底层的批量依赖注入就放在这里面。

在Model实体目录中我们新建一个用于数据库连接的接口IDataBaseSetting.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace TianYa.DotNetShare.SharpCore.Model
{
    public interface IDataBaseSetting
    {
        /// <summary>
        /// 访问数据库连接串
        /// </summary>
        string ConnectionString { get; set; }

        /// <summary>
        /// 数据库名称,当是关系型数据库时,DatabaseName属性没用到
        /// </summary>
        string DatabaseName { get; set; }
    }
}

接着添加一个用于数据库连接的实现类DataBaseSetting.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace TianYa.DotNetShare.SharpCore.Model
{
    public class DataBaseSetting : IDataBaseSetting
    {
        /// <summary>
        /// 访问数据库连接串
        /// </summary>
        public string ConnectionString { get; set; }

        /// <summary>
        /// 数据库名称,当是关系型数据库时,DatabaseName属性没用到
        /// </summary>
        public string DatabaseName { get; set; }
    }
}

该类实现了IDataBaseSetting.cs接口

Model实体目录主要用于以后涉及到数据库访问的时候使用,本demo主要为了简单介绍下如何使用ASP.NET Core内置的IoC容器DI进行批量依赖注入,故没有对该实体目录进行详细的讲解。

接下来就是重头戏了,我们在Extensions扩展目录中添加一个用于批量依赖注入的扩展类ServiceCollectionExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;

using TianYa.DotNetShare.SharpCore.Model;

namespace TianYa.DotNetShare.SharpCore.Extensions
{
    /// <summary>
    /// ServiceCollection扩展
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        #region 通过反射批量注入指定的程序集
        /// <summary>
        /// 通过反射批量注入指定的程序集
        /// </summary>
        /// <param name="services">服务</param>
        /// <param name="assemblyNames">程序集数组 如:["TianYa.DotNetShare.Repository","TianYa.DotNetShare.Service"],无需写dll</param>
        public static void RegisterTianYaSharpService(this IServiceCollection services, params string[] assemblyNames)
        {
            foreach (string assemblyName in assemblyNames)
            {
                foreach (var itemClass in GetClassInterfacePairs(assemblyName))
                {
                    foreach (var itemInterface in itemClass.Value)
                    {
                        if (itemInterface != typeof(DataBaseSetting))
                        {
                            services.AddTransient(itemInterface, itemClass.Key); //DI依赖注入
                        }
                    }
                }
            }
        }
        #endregion

        #region DI依赖注入辅助方法

        /// <summary>
        /// 获取类以及类实现的接口键值对
        /// </summary>
        /// <param name="assemblyName">程序集名称</param>
        /// <returns>类以及类实现的接口键值对</returns>
        private static Dictionary<Type, List<Type>> GetClassInterfacePairs(string assemblyName)
        {
            //存储 实现类 以及 对应接口
            Dictionary<Type, List<Type>> dic = new Dictionary<Type, List<Type>>();
            Assembly assembly = GetAssembly(assemblyName);
            if (assembly != null)
            {
                Type[] types = assembly.GetTypes();
                foreach (var item in types.AsEnumerable().Where(x => !x.IsAbstract && !x.IsInterface && !x.IsGenericType))
                {
                    dic.Add(item, item.GetInterfaces().Where(x => !x.IsGenericType).ToList());
                }
            }

            return dic;
        }

        /// <summary>
        /// 获取所有的程序集
        /// </summary>
        /// <returns>程序集集合</returns>
        private static List<Assembly> GetAllAssemblies()
        {
            var list = new List<Assembly>();
            var deps = DependencyContext.Default;
            var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系统程序集、Nuget下载包
            foreach (var lib in libs)
            {
                try
                {
                    var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
                    list.Add(assembly);
                }
                catch (Exception)
                {
                    // ignored
                }
            }
            return list;
        }

        /// <summary>
        /// 获取指定的程序集
        /// </summary>
        /// <param name="assemblyName">程序集名称</param>
        /// <returns>程序集</returns>
        private static Assembly GetAssembly(string assemblyName)
        {
            return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
        }

        #endregion
    }
}

并且添加一个Dynamic的扩展类DynamicExtensions.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using System.Xml;

namespace TianYa.DotNetShare.SharpCore.Extensions
{
    /// <summary>
    /// Dynamic的扩展方法
    /// </summary>
    public static class DynamicExtensions
    {
        #region 匿名对象处理

        #region 将对象[主要是匿名对象]转换为dynamic
        /// <summary>
        /// 将对象[主要是匿名对象]转换为dynamic
        /// </summary>
        public static dynamic ToDynamic(this object value)
        {
            IDictionary<string, object> expando = new ExpandoObject();
            var type = value.GetType();
            var properties = TypeDescriptor.GetProperties(type);
            foreach (PropertyDescriptor property in properties)
            {
                var val = property.GetValue(value);
                if (property.PropertyType.FullName.StartsWith("<>f__AnonymousType"))
                {
                    dynamic dval = val.ToDynamic();
                    expando.Add(property.Name, dval);
                }
                else
                {
                    expando.Add(property.Name, val);
                }
            }
            return expando as ExpandoObject;
        }
        #endregion

        #region 将对象[主要是匿名对象]转换为List<dynamic>
        /// <summary>
        /// 将对象[主要是匿名对象]转换为List<dynamic>
        /// </summary>
        public static List<dynamic> ToDynamicList(this IEnumerable<dynamic> values)
        {
            var list = new List<dynamic>();
            if (values != null)
            {
                if (values.Any())
                {
                    list.AddRange(values.Select(v => ((object)v).ToDynamic()));
                }
            }

            return list;
        }
        #endregion

        #region 将匿名对象集合转换为XML
        /// <summary>
        /// 将匿名对象集合转换为XML
        /// </summary>
        public static XmlDocument ListObjertToXML(this IEnumerable<dynamic> values)
        {
            var xmlDoc = new XmlDocument();
            var xmlElem = xmlDoc.CreateElement("DocumentElement");
            xmlDoc.AppendChild(xmlElem);
            if (values != null)
            {
                if (values.Any())
                {
                    var node = xmlDoc.SelectSingleNode("DocumentElement");
                    foreach (var item in values)
                    {
                        var xmlRow = xmlDoc.CreateElement("Row");
                        ObjectToXML(item, xmlDoc, xmlRow);
                        node.AppendChild(xmlRow);
                    }
                }
            }

            return xmlDoc;
        }
        #endregion

        #region 将匿名对象填充XML节点
        /// <summary>
        /// 将匿名对象填充XML节点
        /// </summary>
        private static void ObjectToXML(object value, XmlDocument xmlDoc, XmlElement xmlRow)
        {
            IDictionary<string, object> expando = new ExpandoObject();
            var type = value.GetType();
            var properties = TypeDescriptor.GetProperties(type);
            foreach (PropertyDescriptor property in properties)
            {
                var val = property.GetValue(value);
                xmlRow.CloneNode(false);
                var xmlTemp = xmlDoc.CreateElement(property.Name);
                XmlText xmlText;
                if (property.PropertyType.FullName.StartsWith("<>f__AnonymousType"))
                {
                    dynamic dval = val.ToDynamic();
                    xmlText = xmlDoc.CreateTextNode(dval.ObjectToString());
                }
                else
                {
                    xmlText = xmlDoc.CreateTextNode(val.ToString());
                }

                xmlTemp.AppendChild(xmlText);
                xmlRow.AppendChild(xmlTemp);
            }
        }
        #endregion

        #endregion
    }
}

该扩展类主要在我们的Action向视图传递匿名类型值的时候使用

六、Web层

本demo的web项目需要引用以下几个程序集:

1、TianYa.DotNetShare.Model 我们的实体层

2、TianYa.DotNetShare.Service 我们的服务层

3、TianYa.DotNetShare.Repository 我们的仓储层,正常我们的web项目是不应该使用仓储层的,此处我们引用是为了演示IoC依赖注入

4、TianYa.DotNetShare.CommTool 我们的公共工具类库

5、TianYa.DotNetShare.SharpCore 我们的Sharp核心类库

到了这里我们所有的工作都已经准备好了,接下来就是开始做注入工作了。

打开我们的Startup.cs文件进行注入工作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

using TianYa.DotNetShare.SharpCore.Extensions;

namespace TianYa.DotNetShare.CoreMvcDemo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            //DI依赖注入,批量注入指定的程序集
            services.RegisterTianYaSharpService(new string[] { "TianYa.DotNetShare.Repository", "TianYa.DotNetShare.Service" });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

其中用来实现批量依赖注入的只要一句话就搞定了,如下所示:

//DI依赖注入,批量注入指定的程序集
services.RegisterTianYaSharpService(new string[] { "TianYa.DotNetShare.Repository", "TianYa.DotNetShare.Service" });

Sharp核心类库在底层实现了批量注入的逻辑,程序集的注入必须按照先后顺序进行,先进行仓储层注入然后再进行服务层注入。

接下来我们来看看控制器里面怎么弄:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

using TianYa.DotNetShare.CoreMvcDemo.Models;
using TianYa.DotNetShare.Service;
using TianYa.DotNetShare.Repository;

namespace TianYa.DotNetShare.CoreMvcDemo.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        /// 定义仓储层学生抽象类对象
        /// </summary>
        protected IStudentRepository StuRepository;

        /// <summary>
        /// 定义服务层学生抽象类对象
        /// </summary>
        protected IStudentService StuService;

        /// <summary>
        /// 通过构造函数进行注入
        /// 注意:参数是抽象类,而非实现类,因为已经在Startup.cs中将实现类映射给了抽象类
        /// </summary>
        /// <param name="stuRepository">仓储层学生抽象类对象</param>
        /// <param name="stuService">服务层学生抽象类对象</param>
        public HomeController(IStudentRepository stuRepository, IStudentService stuService)
        {
            this.StuRepository = stuRepository;
            this.StuService = stuService;
        }

        public IActionResult Index()
        {
            var stu1 = StuRepository.GetStuInfo("10000");
            var stu2 = StuService.GetStuInfo("10001");
            string msg = $"学号:10000,姓名:{stu1.Name},性别:{stu1.Sex},年龄:{stu1.Age}<br />";
            msg += $"学号:10001,姓名:{stu2.Name},性别:{stu2.Sex},年龄:{stu2.Age}";

            return Content(msg, "text/html", System.Text.Encoding.UTF8);
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

至此,完成处理,接下来就是见证奇迹的时刻了,我们来访问一下/home/index,看看是否能返回学生信息。

我们可以发现,返回了学生的信息,说明我们注入成功了。

另外通过这个例子我们可以发现在注入仓储层对象StudentRepository时,不仅控制器中注入成功了,而且在服务层中也注入成功了,说明我们ASP.NET Core内置的IoC容器DI依赖注入是全局的。

总结:

1、采用的是构造函数注入的方式,在构造函数中初始化赋值。

2、ASP.NET Core内置的IoC容器DI依赖注入是全局的。

参考博文:https://www.cnblogs.com/fei686868/p/11077997.html

版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!

原文地址:https://www.cnblogs.com/xyh9039/p/11373269.html

时间: 2024-11-05 11:46:05

ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入的相关文章

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 Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射

原文:ASP.NET Core Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射 本章主要简单介绍下在ASP.NET Core中如何使用AutoMapper进行实体映射.在正式进入主题之前我们来看下几个概念: 1.数据库持久化对象PO(Persistent Object):顾名思义,这个对象是用来将我们的数据持久化到数据库,一般来说,持久化对象中的字段会与数据库中对应的 table 保持一致. 2.视图对象VO(View Object):视图对象 V

ASP.NET Core Web 应用程序系列(四)- ASP.NET Core 异步编程之async await

原文:ASP.NET Core Web 应用程序系列(四)- ASP.NET Core 异步编程之async await PS:异步编程的本质就是新开任务线程来处理. 约定:异步的方法名均以Async结尾. 实际上呢,异步编程就是通过Task.Run()来实现的. 了解线程的人都知道,新开一个线程来处理事务这个很常见,但是在以往是没办法接收线程里面返回的值的.所以这时候就该await出场了,await从字面意思不难理解,就是等待的意思. 执行await的方法必须是async修饰的,并且是Task

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应用程序—探索

前言 作为一个Windows系统下的开发者,我对于Core的使用机会几乎为0,但是考虑到微软的战略规划,我觉得,Core还是有先了解起来的必要. 因为,目前微软已经搞出了两个框架了,一个是Net标准(.NetFramework),一个是Net Core. 而新特性的更新几乎都是在Net Core这个框架中. 所以,考虑到未来,一旦Core完善了,那微软肯定会放弃现在的.NetFrameWork. 因此,.Net程序员集体改用Net Core,想来,一定是大趋势. 所以让我们怀着探索的精神来看看A

使用docker部署Asp.net core web应用程序--图文教程

要想参考本文做实验,可以参考上一篇文章,关于docker的简单操作,写的比较详细. 拉取aspnetcore最新docker镜像 从阿里云的docker镜像拉取,因为前面我们针对docker镜像做过配置. [[email protected] ~]# docker pull microsoft/aspnetcore 根据你的网速等待拉取成功. [[email protected] ~]# docker images 执行上面的命令,如果能看到aspnetcore镜像,则表示拉取成功. 如果我们想

ASP.NET Core Web 应用程序开发期间部署到IIS自定义主机域名并附加到进程调试

原文:ASP.NET Core Web 应用程序开发期间部署到IIS自定义主机域名并附加到进程调试 想必大家之前在进行ASP.NET Web 应用程序开发期间都有用到过将我们的网站部署到IIS自定义主机域名并附加到进程进行调试. 那我们的ASP.NET Core Web 应用程序又是如何部署到我们的IIS上面进行调试的呢,接下来我们来简单介绍下: 一.安装IIS所需的Host扩展(Windows Server Hosting) 下载地址:https://dotnet.microsoft.com/

循序渐进学.Net Core Web Api开发系列【1】:开发环境

系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.本篇概述 本篇不打算描述如何通过Visual Studio创建一个项目之类的话题,主要描述以下内容: 1.使用NuGet和Bower引入第三方库 2.Linux下安装运行环境 3.关于安装虚拟机时碰到的网络设置的问题 实验环境:Windows 10 ,Visual Studio 2017 ,VM 14 , Cent

在 ASP.NET MVC Web 应用程序中输出 RSS Feeds

RSS全称Really Simple Syndication.一些更新频率较高的网站可以通过RSS让订阅者快速获取更新信息.RSS文档需遵守XML规范的,其中必需包含标题.链接.描述信息,还可以包含发布时间.最后更新时间等信息. 本文将介绍通过LINQ to XML生成XML文档,并在ASP.NET MVC Web应用程序中输出. 在生成RSS文档前,先简单了解一下RSS的结构.根节点rss下有channel节点,channel节点的一些子节点(title,link,description)包含