#asp.net #asp.net-mvc #asp.net-web-api #asp.net-mvc-5 #asp.net-web-api2
#asp.net #asp.net-mvc #asp.net-web-api #asp.net-mvc-5 #asp.net-web-api2
Вопрос:
У меня есть следующее:
- URL-адрес запроса: ‘endpoint/1,2,3?q=foo’
- действие, к которому привязан запрос: панель открытых объектов ([ModelBinder] Список < T> идентификаторов, [FromUri] строка q)
Я хочу сопоставить фрагмент «1,2,3» с параметром «ids», поэтому я создал ModelBinderProvider в соответствии с этой ссылкой, которая должна вызывать надлежащую связующую модель.
public class MyModelBinderProvider: ModelBinderProvider
{
public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
{
IModelBinder modelBinder = null;
if (modelType.IsGenericType amp;amp; (modelType.GetGenericTypeDefinition() == typeof(List<>)))
{
modelBinder = new ListModelBinder();
}
return modelBinder;
}
}
Я зарегистрировал поставщика в Global.asax следующим образом:
GlobalConfiguration.Configuration.Services.Insert(typeof(ModelBinderProvider), 0, new MyModelBinderProvider());
Причина: я создал этого поставщика, потому что я хочу, независимо от того, что такое T (‘1,2,3’ или ‘один, два, три’), привязка к работе.
Проблема: допустим, T равно ‘int’; каждый раз, когда отправляется запрос, параметром ‘ModelType’ всегда является ‘int’, а не то, что я ожидаю — ‘List<int>’, поэтому запрос обрабатывается неправильно.
Странная вещь: выполнение чего-то подобного работает, но T является специализированным, и поэтому я не хочу:
var simpleProvider = new SimpleModelBinderProvider(typeof(List<int>), new ListModelBinder());
GlobalConfiguration.Configuration.Services.Insert(typeof(ModelBinderProvider), 0, simpleProvider);
Я не вижу, что я делаю неправильно, почему параметр ‘ModelType’ не является ожидаемым значением?
Комментарии:
1. Пожалуйста, поясните, почему вы хотели бы это сделать? В каком реальном сценарии вы считаете это полезным? Таким образом, это действительно похоже на взлом чего-то, что может иметь более сложное решение с совершенно другим URI.
Ответ №1:
Это очень старый вопрос, но у меня была аналогичная проблема с устаревшим кодом.
Запятые зарезервированы, и их следует избегать, хотя в некоторых случаях они работают, но если вы действительно хотите их использовать…
Я думаю, что это скорее проблема маршрута, чем связующего для модели, когда «1,2,3» является частью пути URL. Предполагая это, я написал небольшой обработчик маршрута, который делает трюк (пожалуйста, простите очень простой переводчик «слово в целое число»).
CsvRouteHandler получает массив идентификаторов из URL и помещает его в RouteData в виде массива целых чисел. Если исходный массив содержит такие слова, как one, two или three, он преобразует каждое значение в int .
MvcRouteHandler
protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
{
var idArrayParameter = requestContext.RouteData.Values["idArray"] != null ? requestContext.RouteData.Values["idArray"].ToString() : null;
if (string.IsNullOrEmpty(idArrayParameter))
{
return base.GetHttpHandler(requestContext);
}
requestContext.RouteData.Values.Remove("idArray"); // remove the old array from routedata
// Note: it is horrible and bugged but and you probably have your own translation method :)
string[] idArray = idArrayParameter.Split(',');
int[] ids = new int[idArray.Length];
for(int i = 0; i < idArray.Length; i )
{
if (!int.TryParse(idArray[i], out ids[i]))
{
switch (idArray[i])
{
case "one":
ids[i] = 1;
break;
case "two":
ids[i] = 2;
break;
case "three":
ids[i] = 3;
break;
}
}
}
requestContext.RouteData.Values.Add("Id", ids);
return base.GetHttpHandler(requestContext);
}
}
Конфигурация маршрута:
routes.Add(
name: "Id Array Route",
item: new Route(
url: "endpoint/{idArray}",
defaults: new RouteValueDictionary(new { controller = "Test", action = "Index" }),
routeHandler: new CsvRouteHandler())
);