我有很多問題試圖讓我的Web API RESTful POST方法在我的控制器中使用ModelState驗證模型。Web API未執行自定義ActionFilterAttribute
我this網站提到需要創建一個自定義過濾器繼承ActionFilterAttribute
我似乎無法通過單元測試。當單步執行代碼時,它永遠不會遇到OnActionExecuting
方法,並且ModelState.IsValid
總是返回True
。我到處搜索了代碼示例,並嘗試了所有代碼,但都沒有工作。我甚至引用了正確的名稱空間,正如你在下面的代碼中看到的那樣。
ValidationActionFilter.cs
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Linq;
using System.Diagnostics;
namespace OrbitWorksAPI.Filters
{
public class ValidationActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
Debug.WriteLine("ACTION 1 DEBUG pre-processing logging");
var modelState = actionContext.ModelState;
if (actionContext.ActionArguments.Any(kv => kv.Value == null))
actionContext.Response = actionContext.Request
.CreateErrorResponse(HttpStatusCode.BadRequest, "Arguments cannot be null");
if (!modelState.IsValid)
actionContext.Response = actionContext.Request
.CreateErrorResponse(HttpStatusCode.BadRequest, modelState);
}
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Register routes
...
// Register filters
config.Filters.Clear();
config.Filters.Add(new Filters.ValidationActionFilter());
}
}
我有此控制器POST方法:
Controller.cs
[HttpPost]
[ResponseType(typeof(Contracts.Models.IInvoice))]
[ActionFilterAttribute]
public async Task<IHttpActionResult> Post(Contracts.Models.IInvoice invoice)
{
if (!ModelState.IsValid)
BadRequest();
var newInvoice = await _repository.UpsertInvoice(invoice);
if (newInvoice != null)
return CreatedAtRoute<Contracts.Models.IInvoice>("invoice", new { newInvoice.Id }, newInvoice);
return Conflict();
}
我也有一個單元測試:
ControllerUnitTests.cs
[TestMethod]
public async Task POST_New_Invoice_With_Required_Fields_Missing()
{
// Arrange
Contracts.Models.IInvoice model = new Models.Invoice() { };
var config = new HttpConfiguration();
config.Filters.Add(new Filters.ValidationActionFilter());
var repository = new Mock<Contracts.Repository.IInvoiceRepository>();
repository.Setup(x => x.UpsertInvoice(It.IsAny<Contracts.Models.IInvoice>()))
.Returns(Task.FromResult<Contracts.Models.IInvoice>(model));
// set up the controller instance.
var controller = new InvoiceController(repository.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = config;
// Act
var result = await controller.Post(model);
// Assert
var response = result as InvalidModelStateResult;
Assert.IsNotNull(response);
}
和模型:
Invoice.cs
public class Invoice : IInvoice
{
[Key]
public int Id { get; set; }
[Required]
public int InvoiceNo { get; set; }
[Required]
public int CompanyId { get; set; }
[Required]
[MaxLength(50)]
public string CompanyName { get; set; }
[Required]
[MaxLength(250)]
public string InvoiceAddress { get; set; }
[Required]
[MaxLength(250)]
public string SiteAddress { get; set; }
[Required]
public string OrderDate { get; set; }
[Required]
[MaxLength(10)]
public string OrderNo { get; set; }
[Required]
public string OnHire { get; set; }
[Required]
public string InvoiceDate { get; set; }
[Required]
public decimal NettAmount { get; set; }
[Required]
public decimal VATAmount { get; set; }
[Required]
public decimal TotalAmount { get; set; }
[Required]
public bool IsCreditNote { get; set; }
[Required]
public float VATRate { get; set; }
}