65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET Core中的Web API

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (4投票s)

2018 年 4 月 19 日

CPOL

4分钟阅读

viewsIcon

13655

使用.NET Core的Web API

引言

Microsoft提供的最新框架是.NET Core 2.0。今天,我们将学习如何使用.NET Core创建一个简单的Web API。

注意:要理解本文,您必须了解MVC架构、旧的Web API和实体框架。如果您都了解,那就开始吧。

Using the Code

WEB API的基本架构与现有的架构相同。我们使用相同的MVC框架来创建Web API。这里我们要关注的是,为了使WEB API也能在.NET Core框架中运行,我们需要做哪些新的事情。

初始设置

我们不需要安装任何库来运行Web API,因为.NET Core默认包含所有库。但是,如果您想使用任何额外的功能,则需要从NuGet包管理器下载第三方库。在我们的应用程序中,我们使用了以下库。您也可以将它们都包含到您的项目中。

  1. **AutoMapper**:用于将数据库实体映射到模型类
  2. **NLog**:用于将日志写入文件

Dependencies

Startup.cs

Startup.cs是.NET Core应用程序的起点。在这里,您将看到两个函数

  1. ConfigureServices
  2. 配置

1. ConfigureServices

ConfigureServices方法用于设置将在我们的应用程序中使用的依赖项或服务。它使用IServiceCollection接口来定义应用程序内的服务。

在下面的代码中,您将看到我已经使用services.AddSession();配置了会话。除此之外,我们还使用AddMVC来实现MVC架构。在其中,您将看到AddJsonOptions方法。此方法用于设置JSON成员的默认格式和命名约定。

示例

a. 在下面的代码中,我将NamingStrategy设置为null——这意味着无论您对模型JSON成员使用什么大小写,结果都将以该格式显示。例如,如果您在模型中将“id”命名为“ID”,那么它将呈现数据为“ID”。如果您删除此行,则结果将选择默认格式(驼峰式命名),结果将仅呈现为“id”。

 .AddJsonOptions(o =>
                    {
                        if (o.SerializerSettings.ContractResolver != null)
                        {
                            var resolver = 
                                  o.SerializerSettings.ContractResolver as DefaultContractResolver;
                            resolver.NamingStrategy = null;
                        }
                    })
                .AddMvcOptions(o =>
                {
                    o.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                });

b. 我们使用AddCors,用于跨域资源共享。如果我们在两个不同的域上,由于安全问题,JavaScript或浏览器不允许访问服务。因此,在这里,我们告诉我们的应用程序允许哪些CORS。有关CORS的更多信息,请访问此链接

services.AddCors();

2. Configure

Configure方法的目的是配置应用程序的行为。在这里,我们正在配置应用程序中的异常行为、会话和路由。在我的应用程序中,我只使用属性路由。

代码

 public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, 
        // visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            //set default json formatter and output media type

            services.AddSession();
            services.AddMvc()
                .AddJsonOptions(o =>
                    {
                        if (o.SerializerSettings.ContractResolver != null)
                        {
                            var resolver = o.SerializerSettings.ContractResolver 
                                                        as DefaultContractResolver;
                            resolver.NamingStrategy = null;
                        }
                    })
                .AddMvcOptions(o =>
                {
                    o.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
                });

            services.AddCors();
            //Services Injection DI
            services.AddScoped<IRepositoryDB, RepositoryDBContextAccess.RepositoryDB>();
            services.AddScoped<IErrorLog, ErrorLogDB>();

        }

        // This method gets called by the runtime. Use this method to configure 
        // the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory log)
        {
            //Setting of project
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler(appBuilder =>
                {
                    appBuilder.Run(async context =>
                    {
                        context.Response.StatusCode = 500;
                        await context.Response.WriteAsync("Server is down, Try again later");
                    });

                });
            }

            //Status shown on UI
            app.UseStatusCodePages();
            app.UseSession();
            //Logging in debug mode and File
            log.AddDebug();
            log.AddNLog();

            app.UseCors(builder => {
                
                builder.AllowAnyOrigin();
                builder.AllowAnyHeader();
                builder.AllowAnyMethod();
               
            });

            //Automapper to map from entity to model
            AutoMapper.Mapper.Initialize(cfg =>
            {
                cfg.CreateMap<StudentEntity, StudentsModel>().ForMember
                 (model => model.CourseCount, opt =>
                  opt.MapFrom(entity => entity.StudentCourses.Count()));

                cfg.CreateMap<CourseEntity, CourseModel>();

            });

            //Convention based routing
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=student}/{action=GetAllStudents}/{id?}");
            });

        }
    }

学生控制器

我们在这里创建一个名为Student控制器的简单控制器。请注意Web API控制器的区别。我从Controller而不是API控制器继承我的控制器。这就是.NET Core如何将MVC和WebApi结合在一起的。有趣吗?

构造函数

.NET Core现在内置了依赖注入的处理。请注意,我们只需将依赖组件传递到控制器构造函数中,然后在应用程序中使用它。

注意:为了使您的应用程序更好或更易于单元测试,始终使用抽象而不是具体类。使用接口而不是类作为依赖注入。

   //Constructor to inject services(DI)
        public StudentController(IRepositoryDB repository, ILogger<StudentController> log,
            IErrorLog logErrorDb)
        {
            repositoryObject = repository;
            logger = log;
            errorLogDB = logErrorDb;
        }

方法

我们在控制器中声明了两种方法:获取所有学生和根据学生ID获取学生课程。

我们使用HttpGet动词修饰我们的方法。众所周知,Web API基于HTTP协议。我们可以自由地在我们的应用程序中使用所有HTTP动词,例如getpostputpatchdelete等。

HttpGet中,我编写了属性路由,它将告诉客户端需要访问哪个地址来获取资源。因此,当我们访问“www.domain.com/api/getStudents”时,我们将获得所有学生。其他方法也类似。

在我们的方法中,我们使用AutoMapper将DBResult映射到我们的MVC模型类。您已经在本文上面的Startup.cs类中看到了映射。如果您不确定它在哪里,请再次检查。

方法代码

        [HttpGet("api/getStudents")]
        public IActionResult GetAllStudent()
        {
            try
            {
                logger.LogInformation("Controller has been started");
                List<StudentsModel> list = new List<StudentsModel>();
                var result = repositoryObject.GetAllStudent();
                list = Mapper.Map<List<StudentsModel>>(result);
                HttpContext.Session.Set<List<StudentsModel>>("studentObject", list);
                return new JsonResult(list);
            }
            catch (Exception ex)
            {
                errorLogDB.InfoLog(ex.Message, (int)ErrorLogEnum.Error, ex.StackTrace.ToString());

                return null;
            }
            finally
            {
                logger.LogInformation("exception");
            }
        }

        [HttpGet("api/getStudents/{id}/getCourses")]
        public IActionResult GetStudentCourses(int id)
        {
            List<StudentsModel> sessionGet = 
            HttpContext.Session.Get<List<StudentsModel>>("studentObject");
            List<CourseModel> list = new List<CourseModel>();
            var result = repositoryObject.GetStudentCourses(id);
            list = Mapper.Map<List<CourseModel>>(result);
            return new JsonResult(list);
        }

我创建了一个会话管理类,使用我自己的类型来处理会话。借助ISession接口,我们可以扩展会话默认行为的功能。

会话管理

增强会话默认行为的功能。

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace FirstApplication
{
    public static class SessionManagement
    {

        public static void Set<T>(this ISession session, string key, T value)
        {
            session.SetString(key, JsonConvert.SerializeObject(value));
        }

        public static T Get<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
            return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
        }

    }
}

在异常处理中,它将异常记录到数据库中。您可以将其记录到文件和调试窗口中。选择权由您决定。

代码

using AutoMapper;
using FirstApplication.DataSource;
using FirstApplication.Entities;
using FirstApplication.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace FirstApplication.Controllers
{
    public class StudentController : Controller
    {
       
        private IRepositoryDB repositoryObject;
        private ILogger<StudentController> logger;
        private IErrorLog errorLogDB;        

        //Constructor to inject services(DI)
        public StudentController(IRepositoryDB repository, ILogger<StudentController> log,
            IErrorLog logErrorDb)
        {
            repositoryObject = repository;
            logger = log;
            errorLogDB = logErrorDb;
        }
        
        [HttpGet("api/getStudents")]
        public IActionResult GetAllStudent()
        {
            try
            {
                logger.LogInformation("Controller has been started");
                List<StudentsModel> list = new List<StudentsModel>();
                var result = repositoryObject.GetAllStudent();
                list = Mapper.Map<List<StudentsModel>>(result);
                HttpContext.Session.Set<List<StudentsModel>>("studentObject", list);
                return new JsonResult(list);
            }
            catch (Exception ex)
            {
                errorLogDB.InfoLog(ex.Message, (int)ErrorLogEnum.Error, ex.StackTrace.ToString());

                return null;
            }
            finally
            {
                logger.LogInformation("exception");
            }
        }
        
        [HttpGet("api/getStudents/{id}/getCourses")]
        public IActionResult GetStudentCourses(int id)
        {
            List<StudentsModel> sessionGet = 
            HttpContext.Session.Get<List<StudentsModel>>("studentObject");
            List<CourseModel> list = new List<CourseModel>();
            var result = repositoryObject.GetStudentCourses(id);
            list = Mapper.Map<List<CourseModel>>(result);
            return new JsonResult(list);
        }
    }
}

模型

我们为StudentCourse实体分别使用了不同的模型,如下所示

学生模型

  public class StudentsModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int CourseCount { get; set; }
        public string Address { get; set; }
        public List<CourseModel> StudentCourses { get; set; } = new List<CourseModel>();
    }

课程模型

 public class CourseModel
    {
        public int ID { get; set; }
        public string CourseName { get; set; }
        public string CourseDescription { get; set; }        
    }

数据库

在这里,我使用了实体框架的代码优先方法。您可以看到已创建的数据库实体和DbContext,如下所示

要了解有关代码优先实体框架方法的更多信息,请访问此链接

实体

学生实体

public class StudentEntity
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public ICollection<CourseEntity> StudentCourses { get; set; }
    }

课程实体

 public class CourseEntity
    {
        [Key]
        public int ID { get; set; }
        public string CourseName { get; set; }
        public string CourseDescription { get; set; }
        StudentEntity student { get; set; }
        [JsonIgnore]
        public int StudentEntityId { get; set; }
    }

DbContext

DbContext 用于与数据库交互。

  public class StudentDBContext: DbContext
    {
        public StudentDBContext()
        {

        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Connection string here like server name,db ");
        }
        public DbSet<StudentEntity> Students{get;set;}

        public DbSet<CourseEntity> Courses { get; set; }

        public DbSet<ErrorLogEntity> ErrorsLog { get; set; }
    }

工作场景

获取所有学生

All Student Data

获取学生课程

Courses

我希望您会喜欢这篇文章。如果您遇到任何问题或需要在创建Web API方面获得更多帮助,请告诉我。

© . All rights reserved.