首先Nuget中下载包:Microsoft.AspNet.WebApi.SelfHost,如下:
注意版本哦,最高版本只能4.0.30506能用。
1.配置路由
public static class WebApiConfig { public static void Register(this HttpSelfHostConfiguration config) { // 配置JSON序列化设置 config.Formatters.Clear(); config.Formatters.Add(new JsonMediaTypeFormatter()); config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // 配置路由 //config.MapHttpAttributeRoutes(); config.Routes.Clear(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
路由器不要搞错了,其实和老版本asp.net 差不多。
2.创建一个控制器
public class ValuesController : ApiController { [HttpGet] public string HelloWorld() { return "Hello World!"; } [HttpGet] public ModelTest Test() { var model = new ModelTest(); model.Id = Guid.NewGuid().ToString(); model.Name = "Test"; return model; } [HttpGet] public List<ModelTest> Test2() { List<ModelTest> modelTests = new List<ModelTest>(); for (int i = 0; i < 3; i++) { var model = new ModelTest(); model.Id = Guid.NewGuid().ToString(); model.Name = "Test"; modelTests.Add(model); } return modelTests; } }
创建一个WebServer,以来加载实现单例
public class WebServer { private static Lazy<WebServer> _lazy = new Lazy<WebServer>(() => new WebServer()); private ManualResetEvent _webEvent; private WebServer() { } public static WebServer Instance => _lazy.Value; public string BaseAddress { get;set; } public Action<WebServer> StartSuccessfulCallback { get; set; } public Action<WebServer> RunEndCallback { get; set; } public Action<WebServer, AggregateException> StartExceptionCallback { get;set; } public void StartWebServer() { if (string.IsNullOrEmpty(BaseAddress)) return; _webEvent=new ManualResetEvent(false); Task.Factory.StartNew(() => { HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(BaseAddress); config.Register(); using (HttpSelfHostServer server = new HttpSelfHostServer(config)) { try { server.OpenAsync().Wait(); if (StartSuccessfulCallback != null) StartSuccessfulCallback(this); _webEvent.WaitOne(); if (RunEndCallback != null) RunEndCallback(this); } catch (AggregateException ex) { _webEvent.Set(); _webEvent.Close(); _webEvent = null; if (StartExceptionCallback != null) StartExceptionCallback(this,ex); } finally { server.CloseAsync().Wait(); server.Dispose(); } } }); } public void StopWebServer() { if (_webEvent == null) return; _webEvent.Set(); _webEvent.Close(); } }
public class WebApiFactory { static string baseAddress = "http://localhost:9000/"; static WebApiFactory() { Server = WebServer.Instance; Server.BaseAddress = baseAddress; } public static WebServer Server { get;private set; } }
使用
public partial class Form1 : Form { public Form1() { InitializeComponent(); WebApiFactory.Server.StartSuccessfulCallback = (t) => { label1.Text = "Web API hosted on " + t.BaseAddress; }; WebApiFactory.Server.RunEndCallback = (t) => { label1.Text = "Web API End on " + t.BaseAddress; }; WebApiFactory.Server.StartExceptionCallback = (t,ex) => { MessageBox.Show(string.Join(";", ex.InnerExceptions.Select(x => x.Message))); }; } private void button1_Click(object sender, EventArgs e) { WebApiFactory.Server.StartWebServer(); } private void button2_Click(object sender, EventArgs e) { WebApiFactory.Server.StopWebServer(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { WebApiFactory.Server.StopWebServer(); } }
注:启动时必须以管理员身份启动程序
我们挂的是http://localhost:9000/,接下来我们去请求:http://localhost:9000/api/Values/Test2
扩展:简单添加权限验证,不通过路由
public class BasicAuthorizationHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request.Method == HttpMethod.Options) { var optRes = base.SendAsync(request, cancellationToken); return optRes; } if (!ValidateRequest(request)) { var response = new HttpResponseMessage(HttpStatusCode.Forbidden); var content = new Result { success = false, errs = new[] { "服务端拒绝访问:你没有权限" } }; response.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json"); var tsc = new TaskCompletionSource<HttpResponseMessage>(); tsc.SetResult(response); return tsc.Task; } var res = base.SendAsync(request, cancellationToken); return res; } /// <summary> /// 验证信息解密并对比 /// </summary> /// <param name="message"></param> /// <returns></returns> private bool ValidateRequest(HttpRequestMessage message) { var authorization = message.Headers.Authorization; //如果此header为空或不是basic方式则返回未授权 if (authorization != null && authorization.Scheme == "Basic" && authorization.Parameter != null) { string Parameter = authorization.Parameter;// 按理说发送过来的做了加密,这里需要解密 return Parameter == "111";// 身份验证码 } else { return false; } } } /// <summary> /// 构建用于返回错误信息的对象 /// </summary> public class Result { public bool success { get; set; } public string[] errs { get; set; } }
然后在WebApiConfig中注册
// 注册身份验证config.MessageHandlers.Add(new BasicAuthorizationHandler());
根据自己需求做扩展吧,这里由于时间问题简单做身份验证(全局)
根据控制器或方法添加身份验证(非全局):
public class AuthorizationAttribute : AuthorizationFilterAttribute { public override void OnAuthorization(HttpActionContext actionContext) { // 如果验证失败,返回未授权的响应 if (!IsUserAuthorized(actionContext)) { // 如果身份验证失败,返回未授权的响应 var content = new Result { success = false, errs = new[] { "服务端拒绝访问:你没有权限" } }; actionContext.Response= actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized"); actionContext.Response.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json"); } } private bool IsUserAuthorized(HttpActionContext actionContext) { var authorizationHeader = actionContext.Request.Headers.Authorization; if (authorizationHeader != null && authorizationHeader.Scheme == "Bearer" && authorizationHeader.Parameter != null) { // 根据实际需求,进行适当的身份验证逻辑 // 比较 authorizationHeader.Parameter 和预期的授权参数值 return authorizationHeader.Parameter == "111"; } return false; } }
public static class WebApiConfig { public static void Register(this HttpSelfHostConfiguration config) { // 注册身份验证(全局) //config.MessageHandlers.Add(new BasicAuthorizationHandler()); config.Filters.Add(new AuthorizationAttribute()); // 配置JSON序列化设置 config.RegisterJsonFormatter(); // 配置路由 config.RegisterRoutes(); } private static void RegisterJsonFormatter(this HttpSelfHostConfiguration config) { config.Formatters.Clear(); config.Formatters.Add(new JsonMediaTypeFormatter()); config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } private static void RegisterRoutes(this HttpSelfHostConfiguration config) { //config.MapHttpAttributeRoutes(); config.Routes.Clear(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
然后在控制器中:
public class ValuesController : ApiController { [HttpGet] public string HelloWorld() { return "Hello World!"; } [HttpGet] public ModelTest Test() { var model = new ModelTest(); model.Id = Guid.NewGuid().ToString(); model.Name = "Test"; return model; } [Authorization] [HttpGet] public List<ModelTest> Test2() { List<ModelTest> modelTests = new List<ModelTest>(); for (int i = 0; i < 3; i++) { var model = new ModelTest(); model.Id = Guid.NewGuid().ToString(); model.Name = "Test"; modelTests.Add(model); } return modelTests; } }
全局异常处理:
public class GlobalExceptionFilter : IExceptionFilter { public bool AllowMultiple => false; public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { // 在这里实现自定义的异常处理逻辑 // 根据实际需求,处理异常并生成适当的响应 // 示例:将异常信息记录到日志中 LogException(actionExecutedContext.Exception); // 示例:返回带有错误信息的响应 var content = new Result { success = false, errs = new[] { "发生了一个错误" } }; actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Internal Server Error"); actionExecutedContext.Response.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json"); var tcs = new TaskCompletionSource<object>(); tcs.SetResult(null); return tcs.Task; } private void LogException(Exception exception) { // 在这里编写将异常信息记录到日志的逻辑 } }
public static class WebApiConfig { public static void Register(this HttpSelfHostConfiguration config) { // 注册身份验证(全局) //config.MessageHandlers.Add(new BasicAuthorizationHandler()); config.Filters.Add(new AuthorizationAttribute()); // 注册全局异常过滤器 config.Filters.Add(new GlobalExceptionFilter()); // 配置JSON序列化设置 config.RegisterJsonFormatter(); // 配置路由 config.RegisterRoutes(); } private static void RegisterJsonFormatter(this HttpSelfHostConfiguration config) { config.Formatters.Clear(); config.Formatters.Add(new JsonMediaTypeFormatter()); config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } private static void RegisterRoutes(this HttpSelfHostConfiguration config) { //config.MapHttpAttributeRoutes(); config.Routes.Clear(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
写一个测试接口:
[HttpGet] public int Test3() { int a = 3; int b = 0; return a / b; }
我们知道有5个Filter,这里只用到了其中的两个,其它自定义实现