這是一個兩部分的問題。
- 我想將一個 int 值陣列傳遞給我的 REST url,但我收到了一個行內約束例外。我嘗試定義的路線如下
[Route("categories/{categoryId:int}/documenttypes/{documentTypes:int[]}")]
...
...
當被呼叫時,它看起來像這樣:
api/categories/2/documenttypes/{[2,3,4,5]}
任何人都可以指出我如何處理這個內嵌約束例外的正確方向。我找到了幾篇文章,但似乎沒有一篇文章適用于如何處理 int 值陣列。
也許它不可行,我應該將其更改為 POST 請求,但我想我會先嘗試使用 GET 或僅使用字串引數,然后將另一個資源定義添加到我的 REST url,例如
api/config/categories/2/documenttypes/multi?doctype={[1,3,4]}
就 REST 標準而言,此事件是否可接受?
api/categories/2/documenttypes/{[1,3,4]}
我知道我可以將它作為查詢字串傳遞,但我遇到的問題是,如果我這樣做,我最終會遇到 2 個端點沖突:
api/categories/2/documenttypes
沒有引數并回傳給定類別的所有檔案型別
api/categories/2/documenttypes?doctypes={[1,2,3]}
當定義然后呼叫時,我得到一個錯誤,即有多個具有相同定義的端點,因此請求查看我是否可以以某種方式將它作為行內約束傳遞。
希望以上是有道理的。如果沒有,請走開。謝謝
uj5u.com熱心網友回復:
假設動作是
[HttpGet("~/api/categories/{id}/documenttypes")]
public ActionResult GetDocTypes(int id, int[] doctype)
使用這個網址
api/categories/2/documenttypes?doctype=2&doctype=3&doctype=4&doctype=5
uj5u.com熱心網友回復:
我想出了需要更改的各個部分。
首先,我必須添加一個新的路由約束 (
IHttpRouteConstraint) 來處理作為 Web API REST 資源的一部分傳遞的新資料型別:public class HttpRouteConstraintIntArray : IHttpRouteConstraint { public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection) { object value; if (values.TryGetValue(parameterName, out value) && value != null) { var parameters = value.ToString() .Replace("{", string.Empty) .Replace("}", string.Empty) .Replace("[", string.Empty) .Replace("]", string.Empty); var type = typeof(int); var newvalues = parameters.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries) .Select(TypeDescriptor.GetConverter(type) .ConvertFromString).ToArray(); var typedValues = Array.CreateInstance(type, newvalues.Length); newvalues.CopyTo(typedValues, 0); return true; } return false; } }
一旦我宣告了這個新約束,我還必須在 WebApiConfig.cs 中注冊它:
var constraintResolver = new DefaultInlineConstraintResolver();
constraintResolver.ConstraintMap.Add("intarray",
typeof(HttpRouteConstraintIntArray));
config.MapHttpAttributeRoutes(constraintResolver);
但是一旦我做了這些 stanges,我就開始遇到另一個錯誤:
the request contains an entity body but no Content-Type header
get request ....
為了解決這個錯誤,我不得不在端點定義中添加 [FromUri]:
[HttpGet] [Route("categories/{categoryId:int}/documenttypes/ {documentTypeIds:intarray}")] public async Task<IHttpActionResult> GetDataByDocumentTypeIds( int categoryId,[FromUri] int[] documentTypeIds)
現在上面已經通過了這 2 個錯誤,但由于某種原因,documentTypeIds 作為陣列回傳,但它只包含一個值而不是 3,例如它的值是 0 而不是 1,所以顯然需要添加其他內容。
為了處理最后一個問題,我必須創建一個動作過濾器屬性:
public class ArrayInputAttribute : ActionFilterAttribute { private readonly string[] _parameternames; public string Separator { get; set; } public ArrayInputAttribute(params string[] parameternames) { this._parameternames = parameternames; Separator = "-"; } public void ProcessArrayInput(HttpActionContext actionContext, string parametername) { if (actionContext.ActionArguments .ContainsKey(parametername)) { var parameterdescriptor = actionContext.ActionDescriptor.GetParameters() .FirstOrDefault(p => p.ParameterName == parametername); if (parameterdescriptor != null && parameterdescriptor.ParameterType.IsArray) { var type = parameterdescriptor.ParameterType.GetElementType(); var parameters = string.Empty; if (actionContext.ControllerContext.RouteData.Values .ContainsKey(parametername)) { parameters = (string)actionContext.ControllerContext .RouteData.Values[parametername]; } else { var queryString = actionContext.ControllerContext .Request.RequestUri.ParseQueryString(); if (queryString[parametername] != null) { parameters = queryString[parametername]; } } parameters = parameters.ToString() .Replace("{", string.Empty) .Replace("}", string.Empty) .Replace("[", string.Empty) .Replace("]", string.Empty); var values = parameters.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries) Select(TypeDescriptor.GetConverter(type). ConvertFromString).ToArray(); var typedValues = Array.CreateInstance(type, values.Length); values.CopyTo(typedValues, 0); actionContext.ActionArguments[parametername] = typedValues; } } } public override void OnActionExecuting(HttpActionContext actionContext) { foreach (var parameterName in _parameternames) { ProcessArrayInput(actionContext, parameterName); } } }
最后,我必須將屬性添加到端點定義中:
[HttpGet]
[Route("categories/{categoryId:int}/documenttypes/
{documentTypeIds:intarray}")]
[ArrayInputAttribute("documentTypeIds", Separator = ",")]
public async Task<IHttpActionResult> GetDataByDocumentTypeIds(int categoryId,
[FromUri] int[] documentTypeIds)
{
}
一些注意事項:
一些行被拆分,以便在 stackoverflow 中半體面地顯示,顯然不會在 .NET Studio 中作業
上面的代碼是我在谷歌搜索后最終找到的幾篇文章的組合。這些是:
-將整數陣列傳遞給 ASP.NET Web API?
從表面上看,我什至可能不需要約束,我想現在我沒有時間調查因為我需要繼續前進,我會在以后嘗試時發布更新。
Web API 屬性路由路由約束
Web API 屬性路由路由約束
希望以上內容對其他人有所幫助。
謝謝。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/363948.html
標籤:asp.net-mvc 休息 asp.net-web-api
上一篇:將可為空的DateTime欄位更新為null會導致默認DateTime值(0001-01-0100:00:00.0000000)
