C#使用MVC框架创建WebApi服务接口

news2025/1/9 2:45:04

第一步,使用VS2019新建MVC-Web API应用程序

创建BridgeApi

第二步,运行将生成默认的示例网页,网页Url为

https://localhost:44361/home/index

右键 项目 添加 WebAPI控制器类

 添加 

我们可以看到App_Start目录下 有三个文件:

BundleConfig.cs代表 捆绑文件的引用 

有脚本文件ScriptBundle的引用(javascript文件,后缀名.js)

和层叠样式表文件StyleBundle(即css网页排版文件,后缀名.css)

FilterConfig.cs代表全局筛选器

RouteConfig.cs代表url路由模式和action信息

右键,项目,将类库项目更新为控制台应用程序,并添加类Program

添加开源框架Topshelf的引用,添加Owin框架的引用

Topshelf 框架

Topshelf 是一个开源的跨平台的宿主服务框架,支持 Windows 和 Mono,只需要几行代码就可以构建一个很方便使用的服务宿主。

使用 Topshelf 可以非常方便的将一个 C# 控制台程序部署成为一个 Windows Service, 使用它可以很方便的构建跨平台服务寄主,而在调试时直接以控制台的形式运行即可,非常方便。

Owin框架

OWIN 允许 Web 应用从 Web 服务器分离。 它定义了在管道中使用中间件来处理请求和相关响应的标准方法。 WebAPI应用程序和中间件可以与基于 OWIN 的应用程序、服务器和中间件进行互操作。

我们在web.config(有些是app.config)增加webAPI地址和端口

ApiAddress和ApiPort

<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  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 是一个开源的跨平台的宿主服务框架,支持 Windows 和 Mono,只需要几行代码就可以构建一个很方便使用的服务宿主。
* 使用 Topshelf 可以非常方便的将一个 C# 控制台程序部署成为一个 Windows Service, 使用它可以很方便的构建跨平台服务寄主,
* 而在调试时直接以控制台的形式运行即可,非常方便。
* Owin框架
* OWIN 允许 Web 应用从 Web 服务器分离。 它定义了在管道中使用中间件来处理请求和相关响应的标准方法。 
* WebAPI应用程序和中间件可以与基于 OWIN 的应用程序、服务器和中间件进行互操作。
*/

namespace BridgeApi
{
    public class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("WebAPI程序启动开始...");
            HostFactory.Run(new Action<HostConfigurator>(HostConf));
            Console.ReadLine();
        }

        public static void HostConf(HostConfigurator hostConfigurator)
        {
            // 服务使用NETWORK_SERVICE内置帐户运行。身份标识,有好几种方式,如:x.RunAs("username", "password");  x.RunAsPrompt(); x.RunAsNetworkService(); 等
            hostConfigurator.RunAsLocalService();//以服务
            //x.StartAutomatically();//StartModeExtensions
            //x.StartManually();//手动模式

            hostConfigurator.SetDescription("WebAPIServer 斯内科 Topshelf Host服务的描述"); //安装服务后,服务的描述
            hostConfigurator.SetDisplayName("WebAPIServerSnake"); //显示名称
            hostConfigurator.SetServiceName("WebAPIServerSnake"); //服务名称
            Type t = hostConfigurator.GetType();//Topshelf.HostConfigurators.HostConfiguratorImpl
            Console.WriteLine(t.ToString());

            hostConfigurator.Service<TownCrier>(s =>
            {
                s.ConstructUsing(name => new TownCrier());     //配置一个完全定制的服务,对Topshelf没有依赖关系。常用的方式。
                                                               //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 = "服务启动成功。";
                        string urlKey = "ApiAddress";
                        string portKey = "ApiPort";
                        if (!ConfigurationManager.AppSettings.AllKeys.Contains(urlKey))
                        {
                            log = $"服务启动出现异常:App.config文件中不存在配置[{urlKey}]";
                            Console.WriteLine(log);
                            return;
                        }
                        if (!ConfigurationManager.AppSettings.AllKeys.Contains(portKey))
                        {
                            log = $"服务启动出现异常: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 = $"服务启动出现异常:App.config文件中配置[{portKey}]值错误";
                            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 //自动绑定所有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 = $"开始启动服务,服务地址:{urls}";
                        Console.WriteLine(log);

                        //OWIN 托管服务器问题:StartOptions WebApp.Start TargetInvocationException
                        // Start OWIN host ,启动一个webapi程序
                        //  public static IDisposable Start(string url, Action<IAppBuilder> startup);

                        WebApp.Start(options, startup: Configuration);
                        Console.WriteLine($"服务启动成功。");
                        IsStarted = true;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"服务启动出现异常:{ex.Message}");
                        Thread.Sleep(2000);
                    }
                }
            });
        }
        public void Stop()
        {
            Console.WriteLine($"WebApi服务退出");
        }

        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);
        }
    }
}

 控制器类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>
        /// 测试API端口,假设传入一个json字符串{"TestName":"斯内科"}
        /// 请求路由Url不区分大小写
        /// 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 = $"解析失败,请求参数为空,源文本【{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}】上抛数据【{json}】,已处理OK,返回一个随机数【{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 = $"处理时出现错误【{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>
    /// 接口反馈的响应内容对象
    /// </summary>
    public class ResponseContent 
    {
        /// <summary>
        /// 错误号,code为0代表OK
        /// </summary>
        public int Code { get; set; }
        /// <summary>
        /// 错误描述,Code为0,这里显示空
        /// </summary>
        public string Message { get; set; }
        /// <summary>
        /// 相关数据信息,该Data可以是数组、键值对字典、字符串等任意类型数据
        /// </summary>
        public object Data { get; set; }
    }
}

运行,将其按照服务进行

使用PostMan测试WebApi 接口,如下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2273535.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跨年烟花C++代码

嘿&#xff0c;朋友们&#xff01;今天来给大家讲讲一段挺有意思的C代码呀&#xff0c;这段代码主要是用来实现一个烟花效果展示的程序哦&#xff0c;下面咱们一点点来看哈。 效果 1. 开头包含的那些头文件 #include <graphics.h> #include <conio.h> #include &…

Unity 2d描边基于SpriteRender,高性能的描边解决方案

目标 以Unity默认渲染管线为例&#xff0c;打造不需要图片内边距&#xff0c;描边平滑&#xff0c;高性能的描边解决方案 前言 在2d游戏中经常需要给2d对象添加描边&#xff0c;来突出强调2d对象 当你去网上查找2d描边shader&#xff0c;移植到项目里面&#xff0c;大概率会…

自动驾驶相关知识学习笔记

一、概要 因为想知道SIL、HIL是什么仿真工具&#xff0c;故而浏览了自动驾驶相关的知识。 资料来源《自动驾驶——人工智能理论与实践》胡波 林青 陈强 著&#xff1b;出版时间&#xff1a;2023年3月 二、图像的分类、分割与检测任务区别 如图所示&#xff0c;这些更高阶的…

“深入浅出”系列之FFmpeg:(1)音视频开发基础

我的音视频开发大部分内容是跟着雷霄骅大佬学习的&#xff0c;所以笔记也是跟雷老师的博客写的。 一、音视频相关的基础知识 首先播放一个视频文件的流程如下所示&#xff1a; FFmpeg的作用就是将H.264格式的数据转换成YUV格式的数据&#xff0c;然后SDL将YUV显示到电脑屏幕上…

日志服务 SQL 引擎全新升级

作者&#xff1a;戴志勇、顾汉杰&#xff08;执少&#xff09; SQL 作为 SLS 基础功能&#xff0c;每天承载了用户大量日志数据的分析请求&#xff0c;既有小数据量的快速查询&#xff08;如告警、即席查询等&#xff09;&#xff1b;也有上万亿数据规模的报表级分析。SLS 作为…

20250107在WIN10下使用无线ADB连接Andorid7.1.2

connected to 192.168.3.217:5555 adb shell 20250107在WIN10下使用无线ADB连接Andorid7.1.2 2025/1/7 18:12 缘起&#xff1a;公司买了一台6000-7000&#xffe5;的地面站【Andorid7.1.2】&#xff0c;需要通过ifconfig命令来获取其中的网络信息。 虽然系统是VERY非常的陈旧&a…

浙江省自然资源厅:基于“浙里办”的自然资源移动政务服务创新实践——“浙里自然资源”

摘 要&#xff1a;本文基于浙江省自然资源移动政务服务的创新实践&#xff0c;设计和实现“浙里自然资源”应用&#xff0c;依托浙江省省域空间治理数字化平台特有的架构基础&#xff0c;在提升功能性和可用性、加强运营力度、丰富服务内容等方面采取了管理举措和技术创新。通…

使用 Jupyter Notebook:安装与应用指南

文章目录 安装 Jupyter Notebook1. 准备环境2. 安装 Jupyter Notebook3. 启动 Jupyter Notebook4. 选择安装方式&#xff08;可选&#xff09; 二、Jupyter Notebook 的基本功能1. 单元格的类型与运行2. 可视化支持3. 内置魔法命令 三、Jupyter Notebook 的实际应用场景1. 数据…

NeurIPS 2024 | 像素级LLM实现图像视频理解、生成、分割和编辑大统一(昆仑万维等)

Accepted by NeurIPS 2024 文章链接&#xff1a;https://arxiv.org/pdf/2412.19806 项目链接&#xff1a;https://vitron-llm.github.io/ Github链接&#xff1a;https://github.com/SkyworkAI/Vitron 亮点直击 首次提出了一种通用的视觉多模态大语言模型&#xff08;MLLM&…

嵌入式技术之Linux(Ubuntu) 一

一、Linux入门 1.硬件和操作系统以及用户的关系 一个传感器&#xff0c;获得数据后&#xff0c;需要向服务器发送数据。传感器传数据给上位机。 上位机需要一个程序来接收数据&#xff0c;那么这个上位机是什么机器&#xff1f; 我们的笔记本电脑就可以当成上位机。 两个手…

用户界面软件02

基于表单的用户界面 在“基于表单的用户界面”里面&#xff0c;用户开始时选中某个业务处理&#xff08;模块&#xff09;&#xff0c;然后应用程序就使用一系列的表单来引导用户完成整个处理过程。大型机系统上的大部分用户界面都是这样子的。[Cok97]中有更为详细的讨论。 面…

YOLOv8/YOLOv11改进 添加CBAM、GAM、SimAM、EMA、CAA、ECA、CA等多种注意力机制

目录 前言 CBAM GAM SimAM EMA CAA ECA CA 添加方法 YAML文件添加 使用改进训练 前言 本篇文章将为大家介绍Ultralytics/YOLOv8/YOLOv11中常用注意力机制的添加&#xff0c;可以满足一些简单的涨点需求。本文仅写方法&#xff0c;原理不多讲解&#xff0c;需要可跳…

【express-generator】05-路由中间件和错误处理(第一阶段收尾)

一、前言 上篇文章我们介绍了express-generator的请求体解析&#xff0c;重点讲了常用的请求体数据格式&#xff08;JSON/URL 编码的表单数据&#xff09;以及一个FILE文件上传&#xff0c;同时搭配代码示范进行辅助理解。 二、本篇重点 我们继续第一阶段的知识&#xff0c;…

python无需验证码免登录12306抢票 --selenium(2)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 [TOC](python无需验证码免登录12306抢票 --selenium(2)) 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 就在刚刚我抢的票&#xff1a;2025年1月8日…

深度学习驱动的蛋白质设计技术与实践

通过设计特定的蛋白质结构&#xff0c;可以实现预期的生物功能&#xff0c;如催化特定化学反应、识别和结合特定分子、调控生物信号传导等&#xff0c;为生物医学、药物研发、生物技术等领域提供重要工具和解决方案。传统的蛋白质设计方法主要依赖于已知蛋白质结构的同源建模、…

【动态重建】时间高斯分层的长体积视频

标题&#xff1a;Representing Long Volumetric Video with Temporal Gaussian Hierarchy 来源&#xff1a;浙江大学 链接&#xff1a;https://zju3dv.github.io/longvolcap/ 文章目录 摘要一、前言二、主要方法2.1 时间高斯分层2.2 高效渲染2.3 层次结构更新2.4 紧凑的外观模型…

【STM32+CubeMX】 新建一个工程(STM32F407)

相关文章&#xff1a; 【HAL库】 STM32CubeMX 教程 1 --- 下载、安装 目录 第一部分、新建工程 第二部分、工程文件解释 第三部分、编译验证工程 友情约定&#xff1a;本系列的前五篇&#xff0c;为了方便新手玩家熟悉CubeMX、Keil的使用&#xff0c;会详细地截图每一步Cu…

el-date-picker 不响应change事件的解决办法

前言 接到需要把element plus组件的日期时间选择器的input输入框展示隐藏&#xff0c;遇到点击确认按钮change事件不被触发问题&#xff0c;解决办法如下&#xff1a; ①visible-change的回调参考 即根据visible-change的方法里的回调参数进行需要操作 const visibleChange …

api开发如何在代码中使用京东商品详情接口的参数?

选择编程语言和相关工具 以 Python 为例&#xff0c;你可以使用requests库来发送 HTTP 请求获取接口数据。如果是 Java&#xff0c;可以使用OkHttp等库。 Python 示例 假设你已经安装了requests库&#xff0c;以下是一个简单的代码示例来获取和使用京东商品详情接口参数&#…

【docker系列】可视化Docker 管理工具——Portainer

1. 介绍 Portainer是一个可视化的Docker操作界面&#xff0c;提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作&#xff08;包括上传下载镜像&#xff0c;创建容器等操作&#xff09;、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录…