ASP.NET MVC 4 混合 WebForms 项目中 WebApi 部署与配置要点
在传统的 WebForms 架构中整合 ASP.NET MVC 4 及 WebApi 时,发布阶段常因配置冲突导致路由失效或资源无法加载。以下是实现三者共存的关键配置步骤。
1. 程序集引用设置
编译项目时,需检查所有 MVC 相关的依赖程序集属性。确保"复制到本地"(Copy Local)选项被启用,以保证发布后的 bin 目录包含必要的运行时库文件。
2. IIS 处理器解锁
IIS 7 及以上版本默认锁定了部分配置节点以增强安全性。若部署后出现配置错误,需以管理员身份运行命令提示符,解锁 handlers 和 modules 节点。执行以下命令:
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/handlers
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/modules
注意:命令中的节点名称应与报错信息中提示的锁定项一致,且 cmd.exe 必须使用管理员权限启动。
3. Web.config 核心配置
需要在配置文件中注册 Razor 引擎及 MVC 相关的命名空间,确保视图引擎能正确解析。以下是关键的配置节点示例:
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false"/>
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false"/>
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Web.Optimization"/>
</namespaces>
</pages>
</system.web.webPages.razor>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<pages validateRequest="false" controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
</configuration>
4. 路由规则注册
在 Global.asax 的 Application_Start 事件中,需区分 WebForms 资源与 MVC/WebApi 路由。首先忽略静态资源请求,随后注册 API 路由和 MVC 路由。
protected void Application_Start(object sender, EventArgs e)
{
var routeMap = RouteTable.Routes;
// 排除静态资源及 WebForms 特定文件
routeMap.IgnoreRoute("{resource}.axd/{*pathInfo}");
routeMap.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routeMap.IgnoreRoute("{handler}.ashx/{*pathInfo}");
routeMap.IgnoreRoute("ajaxpro/{*pathInfo}");
routeMap.IgnoreRoute("{resource}.asmx/{*pathInfo}");
// 注册 WebApi 路由,支持 Action 名称
routeMap.MapHttpRoute(
name: "ApiRoute",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// 注册 MVC 默认路由
routeMap.MapRoute(
name: "MvcDefault",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
// 配置 WebApi 格式器,仅保留 JSON
var webApiConfig = GlobalConfiguration.Configuration;
webApiConfig.Formatters.Clear();
webApiConfig.Formatters.Add(new JsonMediaTypeFormatter());
}
5. 控制器与客户端调用
定义 Api 控制器时,需注意方法命名与 HTTP 动词的匹配。以下示例展示了如何构建返回 JSON 数据的接口:
public class ProductController : ApiController
{
// 获取列表
public IEnumerable<string> Query()
{
return new string[] { "item1", "item2" };
}
// 根据 ID 获取
public string GetProduct(int productId)
{
var response = new ApiResponse { Id = productId, Success = true, Msg = "查询成功" };
return JsonConvert.SerializeObject(response);
}
// 测试接口
[HttpGet]
public string TestInterface(int productId, string message)
{
var response = new ApiResponse { Id = productId, Success = true, Msg = message };
return JsonConvert.SerializeObject(response);
}
// 提交数据
public string SubmitProduct([FromBody]ApiResponse data)
{
var response = new ApiResponse { Id = data.Id, Success = true, Msg = data.Msg };
return JsonConvert.SerializeObject(response);
}
}
public class ApiResponse
{
public int Id { get; set; }
public bool Success { get; set; }
public string Msg { get; set; }
}
前端通过 AJAX 进行交互时,需指定正确的 URL 路径及 Content-Type:
// GET 请求
$.ajax({
url: "api/product/GetProduct/1",
type: "get",
success: function (data) {
console.log(data);
}
});
// POST 请求
$.ajax({
url: "api/product/SubmitProduct",
type: "post",
data: JSON.stringify({ id: 1, msg: "测试数据" }),
contentType: "application/json",
success: function (data) {
console.log(data);
}
});