1

我刚刚将我的 Web API 帮助页面升级到了 2.1 版。当我尝试打开帮助页面时,出现以下错误:

[ArgumentException: An item with the same key has already been added.]
System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) +52
System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) +10695474
System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) +10
System.Web.Http.Description.ApiExplorer.TryExpandUriParameters(IHttpRoute route, HttpParsedRoute parsedRoute, ICollection`1 parameterDescriptions, String& expandedRouteTemplate) +407
System.Web.Http.Description.ApiExplorer.PopulateActionDescriptions(HttpActionDescriptor actionDescriptor, IHttpRoute route, String localPath, Collection`1 apiDescriptions) +258
System.Web.Http.Description.ApiExplorer.ExploreDirectRoute(HttpControllerDescriptor controllerDescriptor, CandidateAction[] candidates, IHttpRoute route) +358
System.Web.Http.Description.ApiExplorer.InitializeApiDescriptions() +410
System.Lazy`1.CreateValue() +416
System.Lazy`1.LazyInitValue() +152
System.Lazy`1.get_Value() +75
System.Web.Http.Description.ApiExplorer.get_ApiDescriptions() +40
CobaWebApi.Areas.HelpPage.HelpPageConfigurationExtensions.GetHelpPageApiModel(HttpConfiguration config, String apiDescriptionId) in e:\SPIKES\CobaWebApi\Areas\HelpPage\HelpPageConfigurationExtensions.cs:224
CobaWebApi.Areas.HelpPage.Controllers.HelpController.Api(String apiId) in e:\SPIKES\CobaWebApi\Areas\HelpPage\Controllers\HelpController.cs:38
lambda_method(Closure , ControllerBase , Object[] ) +180
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +59
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +435
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +60
System.Web.Mvc.Async.ActionInvocation.InvokeSynchronousActionMethod() +76
System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +36
System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +73
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +136
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +102
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +49
System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +117
System.Web.Mvc.Async.<>c__DisplayClass48.<InvokeActionMethodFilterAsynchronouslyRecursive>b__41() +323
System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +44
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +47
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +136
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +102
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +50
System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +72
System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +185
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +133
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +56
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +40
System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +34
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44
System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +39
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +62
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +39
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +39
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +39
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +40
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9628972
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

我已经将问题追溯到这两个控制器操作:

public class MyController : ApiController
{
    /// <summary>
    /// a quick brown fox
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpGet]
    [ResponseType(typeof(OneResponse))]
    [Route("api/stuff/{Id}")]
    public IHttpActionResult GetOne([FromUri] OneRequest request)
    {
        return Ok(new OneResponse());
    }

    /// <summary>
    /// lazy dog
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpGet]
    [ResponseType(typeof(ManyResponse))]
    [Route("api/stuff")]
    public IHttpActionResult GetMany([FromUri] ManyRequest request)
    {
        return Ok(new ManyResponse());
    }
}

如果我删除 [FromUri],帮助页面将正确显示。如果我使用 [FromUri],它会以某种方式认为这两个端点是相同的。

有解决方法吗?

4

1 回答 1

2

这确实是 ApiExplorer 中的一个错误。提出以下问题: https ://aspnetwebstack.codeplex.com/workitem/1683

可以使用单个操作重现此处的问题。在上述情况下,我相信您IdOneRequest.

解决方法
重命名路由模板上的属性,使其具有不同的大小写,而不是模型属性中的大小写。因此,在这里将模板中的路由参数重命名为Idto ,这应该可以解决您的问题。id

public class OneRequest
{
     public int Id { get; set; }
     ....
}

[Route("api/stuff/{id}")]
public IHttpActionResult GetOne([FromUri] OneRequest request)

实际上,Web API 不应该以区分大小写的方式来匹配这些,这似乎是核心错误,因此您会看到错误。

于 2014-02-13T20:30:19.563 回答