.NET Core中的Web API
使用.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包管理器下载第三方库。在我们的应用程序中,我们使用了以下库。您也可以将它们都包含到您的项目中。
- **AutoMapper**:用于将数据库实体映射到模型类
- **NLog**:用于将日志写入文件
Startup.cs
Startup.cs是.NET Core应用程序的起点。在这里,您将看到两个函数
ConfigureServices
配置
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动词,例如get
、post
、put
、patch
、delete
等。
在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);
}
}
}
模型
我们为Student
和Course
实体分别使用了不同的模型,如下所示
学生模型
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; }
}
工作场景
获取所有学生
获取学生课程
我希望您会喜欢这篇文章。如果您遇到任何问题或需要在创建Web API方面获得更多帮助,请告诉我。