C#使用MVC框架創(chuàng)建WebApi服務(wù)接口的流程步驟
第一步,使用VS2019新建MVC-Web API應(yīng)用程序

創(chuàng)建BridgeApi


第二步,運(yùn)行將生成默認(rèn)的示例網(wǎng)頁(yè),網(wǎng)頁(yè)Url為
https://localhost:44361/home/index

右鍵 項(xiàng)目 添加 WebAPI控制器類(lèi)

添加

我們可以看到App_Start目錄下 有三個(gè)文件:

BundleConfig.cs代表 捆綁文件的引用
有腳本文件ScriptBundle的引用(javascript文件,后綴名.js)
和層疊樣式表文件StyleBundle(即css網(wǎng)頁(yè)排版文件,后綴名.css)
FilterConfig.cs代表全局篩選器
RouteConfig.cs代表url路由模式和action信息
右鍵,項(xiàng)目,將類(lèi)庫(kù)項(xiàng)目更新為控制臺(tái)應(yīng)用程序,并添加類(lèi)Program
添加開(kāi)源框架Topshelf的引用,添加Owin框架的引用

Topshelf 框架
Topshelf 是一個(gè)開(kāi)源的跨平臺(tái)的宿主服務(wù)框架,支持 Windows 和 Mono,只需要幾行代碼就可以構(gòu)建一個(gè)很方便使用的服務(wù)宿主。
使用 Topshelf 可以非常方便的將一個(gè) C# 控制臺(tái)程序部署成為一個(gè) Windows Service, 使用它可以很方便的構(gòu)建跨平臺(tái)服務(wù)寄主,而在調(diào)試時(shí)直接以控制臺(tái)的形式運(yùn)行即可,非常方便。
Owin框架
OWIN 允許 Web 應(yīng)用從 Web 服務(wù)器分離。 它定義了在管道中使用中間件來(lái)處理請(qǐng)求和相關(guān)響應(yīng)的標(biāo)準(zhǔn)方法。 WebAPI應(yīng)用程序和中間件可以與基于 OWIN 的應(yīng)用程序、服務(wù)器和中間件進(jìn)行互操作。
我們?cè)趙eb.config(有些是app.config)增加webAPI地址和端口
ApiAddress和ApiPort
<?xml version="1.0" encoding="utf-8"?>
<!--
有關(guān)如何配置 ASP.NET 應(yīng)用程序的詳細(xì)信息,請(qǐng)?jiān)L問(wèn)
https://go.microsoft.com/fwlink/?LinkId=301880
-->
<configuration>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="ApiAddress" value="" />
<add key="ApiPort" value="45678" />
</appSettings>
</configuration>Program.cs如下:
using Microsoft.Owin.Hosting;
using Owin;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Topshelf;
using Topshelf.HostConfigurators;
/*
* Topshelf 是一個(gè)開(kāi)源的跨平臺(tái)的宿主服務(wù)框架,支持 Windows 和 Mono,只需要幾行代碼就可以構(gòu)建一個(gè)很方便使用的服務(wù)宿主。
* 使用 Topshelf 可以非常方便的將一個(gè) C# 控制臺(tái)程序部署成為一個(gè) Windows Service, 使用它可以很方便的構(gòu)建跨平臺(tái)服務(wù)寄主,
* 而在調(diào)試時(shí)直接以控制臺(tái)的形式運(yùn)行即可,非常方便。
* Owin框架
* OWIN 允許 Web 應(yīng)用從 Web 服務(wù)器分離。 它定義了在管道中使用中間件來(lái)處理請(qǐng)求和相關(guān)響應(yīng)的標(biāo)準(zhǔn)方法。
* WebAPI應(yīng)用程序和中間件可以與基于 OWIN 的應(yīng)用程序、服務(wù)器和中間件進(jìn)行互操作。
*/
namespace BridgeApi
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("WebAPI程序啟動(dòng)開(kāi)始...");
HostFactory.Run(new Action<HostConfigurator>(HostConf));
Console.ReadLine();
}
public static void HostConf(HostConfigurator hostConfigurator)
{
// 服務(wù)使用NETWORK_SERVICE內(nèi)置帳戶(hù)運(yùn)行。身份標(biāo)識(shí),有好幾種方式,如:x.RunAs("username", "password"); x.RunAsPrompt(); x.RunAsNetworkService(); 等
hostConfigurator.RunAsLocalService();//以服務(wù)
//x.StartAutomatically();//StartModeExtensions
//x.StartManually();//手動(dòng)模式
hostConfigurator.SetDescription("WebAPIServer 斯內(nèi)科 Topshelf Host服務(wù)的描述"); //安裝服務(wù)后,服務(wù)的描述
hostConfigurator.SetDisplayName("WebAPIServerSnake"); //顯示名稱(chēng)
hostConfigurator.SetServiceName("WebAPIServerSnake"); //服務(wù)名稱(chēng)
Type t = hostConfigurator.GetType();//Topshelf.HostConfigurators.HostConfiguratorImpl
Console.WriteLine(t.ToString());
hostConfigurator.Service<TownCrier>(s =>
{
s.ConstructUsing(name => new TownCrier()); //配置一個(gè)完全定制的服務(wù),對(duì)Topshelf沒(méi)有依賴(lài)關(guān)系。常用的方式。
//the start and stop methods for the service
s.WhenStarted(tc => tc.Start()); //4
s.WhenStopped(tc => tc.Stop());
});
}
}
public class TownCrier
{
public TownCrier()
{
}
public void Start()
{
Task.Factory.StartNew(() =>
{
bool IsStarted = false;
while (!IsStarted)
{
try
{
string log = "服務(wù)啟動(dòng)成功。";
string urlKey = "ApiAddress";
string portKey = "ApiPort";
if (!ConfigurationManager.AppSettings.AllKeys.Contains(urlKey))
{
log = $"服務(wù)啟動(dòng)出現(xiàn)異常:App.config文件中不存在配置[{urlKey}]";
Console.WriteLine(log);
return;
}
if (!ConfigurationManager.AppSettings.AllKeys.Contains(portKey))
{
log = $"服務(wù)啟動(dòng)出現(xiàn)異常:App.config文件中不存在配置[{portKey}]";
Console.WriteLine(log);
return;
}
string apiUrl = ConfigurationManager.AppSettings[urlKey].ToString();
string apiPort = ConfigurationManager.AppSettings[portKey].ToString();
bool rtn = int.TryParse(apiPort, out int port);
if (!rtn)
{
log = $"服務(wù)啟動(dòng)出現(xiàn)異常:App.config文件中配置[{portKey}]值錯(cuò)誤";
Console.WriteLine(log);
return;
}
StartOptions options = new StartOptions();
//options.Urls.Add($"http://localhost:{apiPort}");
options.Urls.Add($"http://127.0.0.1:{apiPort}");
//options.Urls.Add($"http://{Environment.MachineName}:{apiPort}");
if (!string.IsNullOrEmpty(apiUrl))
{
options.Urls.Add($"http://{apiUrl}:{apiPort}");
}
else
{
#region //自動(dòng)綁定所有IP
string hostName = Dns.GetHostName();
IPAddress[] iPAddresses = Dns.GetHostAddresses(hostName);
foreach (IPAddress ipAddress in iPAddresses)
{
//IPv4
if (ipAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
options.Urls.Add($"http://{ipAddress}:{apiPort}");
}
}
#endregion
}
string urls = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(options.Urls);
log = $"開(kāi)始啟動(dòng)服務(wù),服務(wù)地址:{urls}";
Console.WriteLine(log);
//OWIN 托管服務(wù)器問(wèn)題:StartOptions WebApp.Start TargetInvocationException
// Start OWIN host ,啟動(dòng)一個(gè)webapi程序
// public static IDisposable Start(string url, Action<IAppBuilder> startup);
WebApp.Start(options, startup: Configuration);
Console.WriteLine($"服務(wù)啟動(dòng)成功。");
IsStarted = true;
}
catch (Exception ex)
{
Console.WriteLine($"服務(wù)啟動(dòng)出現(xiàn)異常:{ex.Message}");
Thread.Sleep(2000);
}
}
});
}
public void Stop()
{
Console.WriteLine($"WebApi服務(wù)退出");
}
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
}控制器類(lèi)BridgeController如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace BridgeApi
{
[RoutePrefix("Bridge")]
public class BridgeController : ApiController
{
/// <summary>
/// 測(cè)試API端口,假設(shè)傳入一個(gè)json字符串{"TestName":"斯內(nèi)科"}
/// 請(qǐng)求路由Url不區(qū)分大小寫(xiě)
/// http://127.0.0.1:45678/Bridge/testApi
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
[Route("TestApi")]
[HttpPost]
public HttpResponseMessage TestApi(object objText)
{
try
{
Microsoft.Owin.OwinContext context = ((Microsoft.Owin.OwinContext)Request.Properties["MS_OwinContext"]);
string RemoteClient = context.Request.RemoteIpAddress + ":" + context.Request.RemotePort;
if (objText == null)
{
string returnDataNG = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseContent()
{
Code = 12345,
Message = $"解析失敗,請(qǐng)求參數(shù)為空,源文本【{objText}】"
});
return new HttpResponseMessage()
{
Content = new StringContent(returnDataNG, System.Text.Encoding.UTF8, mediaType: "application/json")
};
}
string json = objText.ToString();
TestClass testClass = Newtonsoft.Json.JsonConvert.DeserializeObject<TestClass>(json);
if (testClass == null || string.IsNullOrEmpty(testClass.TestName))
{
string returnDataNG = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseContent()
{
Code = 12345,
Message = $"解析失敗,TestName為空,源json【{json}】"
});
return new HttpResponseMessage()
{
Content = new StringContent(returnDataNG, System.Text.Encoding.UTF8, mediaType: "application/json")
};
}
string returnData = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseContent()
{
Code = 0,
Message = "",
Data = $"接收到【{RemoteClient}】上拋數(shù)據(jù)【{json}】,已處理OK,返回一個(gè)隨機(jī)數(shù)【{new Random().Next(1, 100)}】"
});
return new HttpResponseMessage()
{
Content = new StringContent(returnData, System.Text.Encoding.UTF8, mediaType: "application/json")
};
}
catch (Exception ex)
{
string returnDataNG = Newtonsoft.Json.JsonConvert.SerializeObject(new ResponseContent()
{
Code = -1,
Message = $"處理時(shí)出現(xiàn)錯(cuò)誤【{ex.Message}】"
});
return new HttpResponseMessage()
{
Content = new StringContent(returnDataNG, System.Text.Encoding.UTF8, mediaType: "application/json"),
StatusCode = HttpStatusCode.BadRequest
};
}
}
}
public class TestClass
{
public string TestName { get; set; }
}
/// <summary>
/// 接口反饋的響應(yīng)內(nèi)容對(duì)象
/// </summary>
public class ResponseContent
{
/// <summary>
/// 錯(cuò)誤號(hào),code為0代表OK
/// </summary>
public int Code { get; set; }
/// <summary>
/// 錯(cuò)誤描述,Code為0,這里顯示空
/// </summary>
public string Message { get; set; }
/// <summary>
/// 相關(guān)數(shù)據(jù)信息,該Data可以是數(shù)組、鍵值對(duì)字典、字符串等任意類(lèi)型數(shù)據(jù)
/// </summary>
public object Data { get; set; }
}
}運(yùn)行,將其按照服務(wù)進(jìn)行

使用PostMan測(cè)試WebApi 接口,如下

以上就是C#使用MVC框架創(chuàng)建WebApi服務(wù)接口的流程步驟的詳細(xì)內(nèi)容,更多關(guān)于C# MVC創(chuàng)建WebApi接口的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#使用System.Threading.Timer實(shí)現(xiàn)計(jì)時(shí)器的示例詳解
以往一般都是用 System.Timers.Timer 來(lái)做計(jì)時(shí)器,其實(shí) System.Threading.Timer 也可以實(shí)現(xiàn)計(jì)時(shí)器功能,下面就跟隨小編一起來(lái)學(xué)習(xí)一下如何使用System.Threading.Timer實(shí)現(xiàn)計(jì)時(shí)器功能吧2024-01-01
逐步講解快速排序算法及C#版的實(shí)現(xiàn)示例
快速排序在時(shí)間復(fù)雜度同為O(N*logN)的幾種排序方法中效率較高,因而比較常用,接下來(lái)這里就來(lái)逐步講解快速排序算法及C#版的實(shí)現(xiàn)示例2016-06-06
C#提取文件時(shí)間戳實(shí)現(xiàn)實(shí)現(xiàn)與性能優(yōu)化
這篇文章主要為大家詳細(xì)介紹了如何高效地從CAN ASC文件中提取時(shí)間戳數(shù)據(jù),并分享一個(gè)高性能的C#實(shí)現(xiàn)方案,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-06-06
在C#中根據(jù)控件名稱(chēng)獲取控件實(shí)例的方法
這篇文章主要介紹了在C#中根據(jù)控件名稱(chēng)遍歷并獲取窗口或容器中控件實(shí)例的兩種方法,分別是WinForms中的Control.Find方法和遞歸遍歷,以及WPF中的LogicalTreeHelper.FindLogicalNode和遞歸遍歷邏輯樹(shù),需要的朋友可以參考下2026-01-01
WPF自定義TreeView控件樣式實(shí)現(xiàn)QQ聯(lián)系人列表效果
TreeView控件在項(xiàng)目中使用比較頻繁,下面這篇文章主要給大家介紹了關(guān)于WPF自定義TreeView控件樣式實(shí)現(xiàn)QQ聯(lián)系人列表效果的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2018-04-04
C# 中的委托與事件實(shí)現(xiàn)靈活的回調(diào)機(jī)制(應(yīng)用場(chǎng)景分析)
委托提供了一種類(lèi)型安全的方式將方法作為參數(shù)傳遞,而事件則允許對(duì)象通知其他對(duì)象發(fā)生了某些事情,這篇文章主要介紹了C# 中的委托與事件實(shí)現(xiàn)靈活的回調(diào)機(jī)制,需要的朋友可以參考下2024-12-12
c#對(duì)XML文檔的創(chuàng)建與增刪改查的示例代碼
這篇文章主要介紹了c#對(duì)XML文檔的創(chuàng)建與增刪改查的示例代碼,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07

