首先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,這里只用到了其中的兩個,其它自定義實現