You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从服务器端ASP.NET MVC门户调用本地Windows服务API?

一、Windows服务中API URL结构优化与配置

你当前的路由配置可以调整得更规范,同时补充必要的格式化和跨域支持,适配后续Web应用的调用需求:

修改后的服务启动代码

protected override void OnStart(string[] args)
{
    // 监听所有网卡的8085端口,若仅需本地调用可改为http://localhost:8085/
    HttpSelfHostConfiguration config = new HttpSelfHostConfiguration("http://*:8085/");
    
    // 配置JSON返回格式,移除XML格式化器
    config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = 
        new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
    config.Formatters.Remove(config.Formatters.XmlFormatter);

    // 配置带api前缀的路由,更符合RESTful规范
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

    // 启用跨域(后续Web应用调用需要)
    config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

    using (HttpSelfHostServer server = new HttpSelfHostServer(config))
    {
        server.OpenAsync().Wait();
        LogEvent("Printing API Service started on http://*:8085/api/");
    }
}

注意:需要先安装Microsoft.AspNet.WebApi.Cors NuGet包才能启用跨域。

示例打印控制器

创建对应的API控制器,实现打印逻辑:

public class PrintController : ApiController
{
    // GET 请求示例:http://localhost:8085/api/print/testprint/1001
    [HttpGet]
    public IHttpActionResult TestPrint(int id)
    {
        // 这里替换为实际打印测试逻辑
        return Ok($"打印任务 {id} 已接收");
    }

    // POST 请求示例:http://localhost:8085/api/print/printdocument
    [HttpPost]
    public IHttpActionResult PrintDocument([FromBody] PrintRequest request)
    {
        if (request == null || string.IsNullOrEmpty(request.DocumentContent))
        {
            return BadRequest("打印请求参数无效");
        }
        
        // 调用自定义打印工具类执行打印
        bool isSuccess = PrintHelper.ExecutePrint(request.DocumentContent, request.PrinterName);
        return isSuccess ? Ok("打印完成") : InternalServerError(new Exception("打印失败"));
    }
}

// 打印请求模型
public class PrintRequest
{
    public string DocumentContent { get; set; }
    public string PrinterName { get; set; }
}

关键配置注意事项

  • 端口权限:运行Windows服务的账户需要绑定端口的权限,可通过管理员命令执行netsh http add urlacl url=http://*:8085/ user=DOMAIN\Username预留权限
  • 防火墙设置:确保Windows防火墙开放8085端口,允许传入连接
  • 监听地址:若需要服务器或局域网设备访问,不能仅监听localhost,需用*:8085或电脑内网IP(如http://192.168.1.105:8085/)
二、ASP.NET MVC Web应用调用本地Printing API的两种方案

由于Windows服务运行在用户本地电脑,Web应用部署在服务器,需根据业务需求选择调用方式:

方案1:前端直接调用本地API

无需服务器中转,直接由浏览器和本地服务交互,延迟更低:

<script>
    async function startPrint() {
        const printParams = {
            DocumentContent: "这是测试打印内容",
            PrinterName: "默认打印机"
        };
        try {
            // 调用用户本地的API服务
            const res = await fetch('http://localhost:8085/api/print/printdocument', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(printParams)
            });
            const result = await res.json();
            alert(result);
        } catch (err) {
            alert("调用本地打印服务失败,请确认服务已启动");
        }
    }
</script>

<button onclick="startPrint()">触发本地打印</button>

方案2:Web后端中转调用

如果需要服务器参与权限验证、日志记录等逻辑,可通过MVC控制器转发请求:

public class PrintManageController : Controller
{
    private readonly HttpClient _httpClient;

    public PrintManageController()
    {
        _httpClient = new HttpClient();
    }

    [HttpPost]
    public async Task<JsonResult> TriggerLocalPrint(PrintRequest request)
    {
        // 获取用户本地电脑的IP(局域网场景有效)
        string userLocalIp = Request.UserHostAddress;
        string apiUrl = $"http://{userLocalIp}:8085/api/print/printdocument";
        
        try {
            var response = await _httpClient.PostAsJsonAsync(apiUrl, request);
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsStringAsync();
            return Json(new { success = true, msg = result });
        } catch (HttpRequestException ex) {
            return Json(new { success = false, msg = $"调用失败:{ex.Message}" });
        }
    }
}

前端通过AJAX调用后端接口:

<script>
    async function triggerPrint() {
        const printData = {
            DocumentContent: "后端中转测试打印",
            PrinterName: "默认打印机"
        };
        try {
            const res = await fetch('/PrintManage/TriggerLocalPrint', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
                },
                body: JSON.stringify(printData)
            });
            const result = await res.json();
            alert(result.msg);
        } catch (err) {
            alert("请求失败");
        }
    }
</script>
三、核心注意事项
  • 网络可达性:用户电脑和服务器必须在同一局域网;若为公网访问,需使用内网穿透工具暴露本地8085端口
  • 服务状态处理:Web应用需增加服务未启动的异常捕获和提示
  • 权限控制:Windows服务运行账户需具备打印权限,生产环境需限制跨域来源为Web应用域名,可添加API密钥验证防止未授权调用

内容的提问来源于stack exchange,提问作者Suzy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 08:52:02