向Web API提交富文本遇危险值检测错误的解决问询
你遇到的这个"A potentially dangerous Request.Form value was detected"错误,本质是ASP.NET的请求验证机制把Summernote生成的HTML富文本当成了危险内容拦截了。虽然你尝试了关闭验证的配置和特性,但因为Web API和MVC的请求处理管道不一样,这些配置没起到预期作用,下面给你几个可行的解决方案:
一、用Web API原生方式处理Multipart请求(推荐)
你当前直接读取System.Web.HttpContext.Current.Request.Form的方式会触发ASP.NET的请求验证,换成Web API提供的MultipartFormDataStreamProvider来读取Multipart内容,就能绕过这个验证,同时更规范地处理文件和表单数据:
using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; using System.Web.Http; using Newtonsoft.Json; [HttpPost] public async Task<IHttpActionResult> Generate() { try { if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } // 创建临时文件存储提供者,也可以指定自定义存储路径 var provider = new MultipartFormDataStreamProvider(Path.GetTempPath()); await Request.Content.ReadAsMultipartAsync(provider); // 读取富文本内容并反序列化到实体类 string contentJson = provider.FormData.GetValues("fileContent").FirstOrDefault(); if (!string.IsNullOrEmpty(contentJson)) { // 替换Transaction为你的实际实体类 var transaction = JsonConvert.DeserializeObject<Transaction>(contentJson); // 编写你的业务处理逻辑 } // 处理上传的文件 foreach (var fileData in provider.FileData) { string originalFileName = fileData.Headers.ContentDisposition.FileName.Trim('"'); string tempFilePath = fileData.LocalFileName; // 可将临时文件迁移至目标目录,或直接读取文件内容 } return Ok("处理成功"); } catch (Exception ex) { return BadRequest(ex.Message); } }
二、针对Web API配置关闭请求验证
如果你坚持要使用Request.Form读取数据,需要针对Web API的管道来关闭验证,而非使用MVC的特性:
- 在
WebApiConfig.cs中添加配置(推荐针对单个控制器/方法,而非全局关闭):
using System.Web.Http.Validation; public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 其他配置代码... // 若要针对单个方法,可直接在控制器方法上添加该特性 config.Filters.Add(new ValidateInputAttribute(false)); } }
- 确保Web.config中的配置正确(针对传统ASP.NET管道):
<system.web> <httpRuntime requestValidationMode="2.0" /> <pages validateRequest="false" /> </system.web>
注意:[System.Web.Mvc.ValidateInput(false)]是MVC控制器专属特性,Web API控制器需要使用System.Web.Http.Validation.ValidateInputAttribute,不要混淆两者。
三、前端代码优化(可选)
你的前端代码将$scope.transaction包裹在fileContent对象中序列化,后端反序列化时需要对应这个结构;也可以直接序列化$scope.transaction,让后端处理更简洁:
$scope.transaction = {}; var files = $scope.myFile; var fd = new FormData(); angular.forEach(files, function (value, key) { fd.append("file" + key, value[0]); }); // 直接序列化transaction,无需额外包裹一层 fd.append("fileContent", JSON.stringify($scope.transaction)); dataService.uploadFile(baseAddress + "/Generate", fd) .success(function (data) {}) .error(function (data) {});
为什么之前的方法没用?
你添加的[System.Web.Mvc.ValidateInput(false)]是给MVC控制器使用的,而你的接口是Web API控制器,两者属于不同的请求处理管道,因此该特性无法生效。另外,直接读取Request.Form会触发ASP.NET的请求验证,而MultipartFormDataStreamProvider是直接读取请求流,不会触发该验证逻辑。
内容的提问来源于stack exchange,提问作者codegrid

