Build a Web API project and webapi
1. Create a running Web API Project
1. Create an empty ASP. NET Web application
2. Use NuGet to introduce Web APIs
In this case, my packages
<?xml version="1.0" encoding="utf-8"?><packages> <package id="Microsoft.AspNet.Cors" version="5.2.3" targetFramework="net45" /> <package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45" /> <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" /> <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" /> <package id="Microsoft.AspNet.WebApi.Cors" version="5.2.3" targetFramework="net45" /> <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" /> <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" /></packages>
3. Create a WebApiConfig. cs class under App_Start as the api STARTUP configuration class.
The Code is as follows:
Using System. web. http; using System. web. http. cors; namespace Frozen. API {public class WebApiConfig {public static void Register (HttpConfiguration config) {// enable cross-origin var cors = new EnableCorsAttribute ("*", "*", "*"); config. enableCors (cors); // Web API routes config. mapHttpAttributeRoutes (); config. routes. mapHttpRoute (name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new {id = RouteParameter. optional });}}}
4. Add "Global application class" Global. asax
The Application_Start method is as follows:
protected void Application_Start(object sender, EventArgs e) { GlobalConfiguration.Configure(WebApiConfig.Register); }
5. Add a Web API controller class, such as "StudentController"
The initial code is as follows (there is also a common Patch method)
using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Http;using System.Web.Http;namespace Frozen.API.Controllers{ public class StudentController : ApiController { // GET api/<controller> public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/<controller>/5 public string Get(int id) { return "value"; } // POST api/<controller> public void Post([FromBody]string value) { } // PUT api/<controller>/5 public void Put(int id, [FromBody]string value) { } // DELETE api/<controller>/5 public void Delete(int id) { } }}
6. Bind a test Domain Name
Don't forget to point
7. I feel like I can run it. When I started the program, I didn't even go into Global, and reported 500 directly. The error message is "unable to read the configuration file due to insufficient Permissions".
Obvious permission issues, solution folder, right-click Properties, Security tab, add 'everone', and open 'modify' to solve the problem
8. Add a breakpoint at 'public string Get (int id) 'in advance and enter 'HTTP: // api.frozen.com/api/student/1' in the browser'
Hit breakpoint
2. Build a basic framework
1. I set up the initial architecture according to the ABC.
2. Register Autofac
Install Autofac from NuGet. The key code is as follows:
public static void SetAutofacContainer() { var builder = new ContainerBuilder(); builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); builder.RegisterType<InMemoryCache>().As<ICache>().InstancePerLifetimeScope(); builder.RegisterAssemblyTypes(typeof(StuEducationRepo).Assembly) .Where(t => t.Name.EndsWith("Repo")) .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterAssemblyTypes(typeof(StudentManager).Assembly) .Where(t => t.Name.EndsWith("Manager")) .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterAssemblyTypes(typeof(StuEducationAppService).Assembly) .Where(t => t.Name.EndsWith("AppService")) .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration); IContainer container = builder.Build(); var resolver = new AutofacWebApiDependencyResolver(container); // Configure Web API with the dependency resolver. GlobalConfiguration.Configuration.DependencyResolver = resolver; }
3. Register AutoMapper
Install AutoMapper from NuGet. The key code is as follows:
Mapper.Initialize(x => { x.AddProfile<DomainToDtoProfile>(); x.AddProfile<DtoToDomainProfile>(); });
public class DomainToDtoProfile : Profile { public override string ProfileName { get { return "DomainToDtoMappings"; } } protected override void Configure() { Mapper.CreateMap<TB_Stu_Education, StuEducationDto>() .ForMember(dest => dest.DegreeName, opt => opt.ResolveUsing<DegreeNameResolver>().FromMember(s => s.DegreeId)) ; } }
4. Register log4net
Install log4net from NuGet. The key code is as follows: add the configuration file \ Config \ log4net. config"
log4net.Config.XmlConfigurator.Configure( new System.IO.FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\\Config\\log4net.config") );
Public class Log4NetLogger: ILogger {private static readonly ILog loginfo; private static readonly ILog logerror; private static readonly ILog logmonitor; static Log4NetLogger () {// different types of logs are stored in different directories. loginfo = LogManager. getLogger ("loginfo"); logerror = LogManager. getLogger ("logerror"); logmonitor = LogManager. getLogger ("logmonitor");} public void Info (string message) {if (loginfo. isInfoEnab Led) loginfo. info (message);} public void InfoFormat (string format, params object [] args) {if (loginfo. isInfoEnabled) loginfo. infoFormat (format, args);} public void Warn (string message) {if (loginfo. isWarnEnabled) loginfo. warn (message);} public void Error (string message, Exception ex = null) {if (logerror. isErrorEnabled) {if (ex! = Null) {logerror. error (message, ex);} else {logerror. error (message) ;}} public void Monitor (string message) {if (logmonitor. isInfoEnabled) logmonitor. info (message );}}
Iii. API debugging (Fiddler)
1. GET
Http://api.frozen.com/api/StuEducation/1
Return: {"DegreeName": "Undergraduate", "Id": 1, "StuId": 1, "DegreeId": 2, "SchoolName": "Anhui University ", "MajorName": "Computer Science and Technology", "StartDate": "00:00:00", "EndDate": "00:00:00", "CreateTime": "00:00:00 ", "LastModifyTime": null}
Code:
public StuEducationDto Get(int id) { var dto = _stuEducationAppService.GetDTOById(id); return dto; }
2. Add POST
Return
HTTP/1.1 201 Created
Code:
public HttpResponseMessage Post([FromBody]StuEducationDto dto) { int result = _stuEducationAppService.CreateByDTO(dto); return result > 0 ? Request.CreateResponse(HttpStatusCode.Created) : Request.CreateResponse(HttpStatusCode.InternalServerError); }
3. Add/modify PUT
Code:
public HttpResponseMessage Put(int id, [FromBody]StuEducationDto dto) { var result = _stuEducationAppService.CreateOrUpdateByDTO(id, dto); return result > 0 ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateResponse(HttpStatusCode.InternalServerError); }
4. Patch local update
Code (using dynamic parameters ):
public HttpResponseMessage Patch(int id, dynamic dtoUpdate) { var dto = _stuEducationAppService.GetDTOById(id); if (dto == null) { return Request.CreateResponse(HttpStatusCode.PaymentRequired); } foreach (JProperty prop in dtoUpdate) { switch (prop.Name.ToLower()) { case "degreeid": dto.DegreeId = prop.Value.ToObject<int>(); break; case "schoolname": dto.SchoolName = prop.Value.ToObject<string>(); break; case "majormame": dto.SchoolName = prop.Value.ToObject<string>(); break; case "startdate": dto.StartDate = prop.Value.ToObject<DateTime>(); break; case "enddate": dto.EndDate = prop.Value.ToObject<DateTime>(); break; default: break; } } var result = _stuEducationAppService.UpdateByDTO(id, dto); return result > 0 ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateResponse(HttpStatusCode.NotFound); }
5. Delete
Code:
public HttpResponseMessage Delete(int id) { var result = _stuEducationAppService.DeleteById(id); return result > 0 ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateResponse(HttpStatusCode.NotFound); }
Attachment: source code download
4. Domain events DomainEvents
Thanks to Uncle warehouse for sharing. Here we only post the source code not provided by Uncle: ActionDelegatedEventHandler <TEvent> class.
public class ActionDelegatedEventHandler<TEvent> : IEventHandler<TEvent> where TEvent : IEvent { private Action<TEvent> func; public ActionDelegatedEventHandler(Action<TEvent> func) { this.func = func; } public void Handle(TEvent evt) { func(evt); } }
Example:
Static void Main (string [] args) {EventBus. instance. subscribe (new DeleteStudentHandler_SendEmailToStudent (); EventBus. instance. subscribe (new DeleteStudentHandler_SendEmailToStudent (); EventBus. instance. subscribe (new ActionDelegatedEventHandler <DeleteStudentEvent> (o => {Thread. sleep (1, 100); Console. writeLine ("student Id: {0}", o. stuId) ;})); EventBus. instance. subscribe (new ActionDelegatedEventHandler <DeleteStudentEvent> (o => {Thread. sleep (1, 100); Console. writeLine ("student Id: {0}", o. stuId) ;}); var entity = new DeleteStudentEvent {StuId = 1}; Console. writeLine ("Event: delete a student, student Id: {0}", entity. stuId); EventBus. instance. publish (entity); Console. writeLine ("over"); Console. readKey ();}