Как создать ограничение маршрута типа System.Guid?
Может ли кто-нибудь указать мне в правильном направлении, как сопоставить маршрут, для которого требуются два указателя?
т. http://blah.com/somecontroller/someaction/ {firstGuid}/{secondGuid}
где оба firstGuid и secondGuid не являются необязательными и должны быть типа system.Guid?
Ответы
Ответ 1
Создайте RouteConstraint, как показано ниже:
public class GuidConstraint : IRouteConstraint {
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (values.ContainsKey(parameterName))
{
string stringValue = values[parameterName] as string;
if (!string.IsNullOrEmpty(stringValue))
{
Guid guidValue;
return Guid.TryParse(stringValue, out guidValue) && (guidValue != Guid.Empty);
}
}
return false;
}}
Далее при добавлении маршрута:
routes.MapRoute("doubleGuid", "{controller}/{action}/{guid1}/{guid2}", new { controller = "YourController", action = "YourAction" }, new { guid1 = new GuidConstraint(), guid2 = new GuidConstraint() });
Ответ 2
Для MVC 5 уже реализован класс GuidRouteConstraint:
https://msdn.microsoft.com/en-us/library/system.web.mvc.routing.constraints.guidrouteconstraint(v=vs.118).aspx
Полный список доступных ограничений MVC:
https://msdn.microsoft.com/en-us/library/system.web.mvc.routing.constraints(v=vs.118).
Ответ 3
Если вы используете код kazimanzurrashid, обязательно включите комментарий Nikos D. Я закончил с этим:
public class NonEmptyGuidRouteConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (values.ContainsKey(parameterName))
{
var guid = values[parameterName] as Guid?;
if (!guid.HasValue)
{
var stringValue = values[parameterName] as string;
if (!string.IsNullOrWhiteSpace(stringValue))
{
Guid parsedGuid;
Guid.TryParse(stringValue, out parsedGuid);
guid = parsedGuid;
}
}
return (guid.HasValue && guid.Value != Guid.Empty);
}
return false;
}
}
Ответ 4
Определенно опасайтесь кода, данного @kazimanzurrashid. Это было хорошее начало, но у него определенно есть ошибка или тоже. Я передавал реальный Guid в значениях маршрута (вместо строки Guid), и я не мог получить ничего, чтобы соответствовать моему маршруту. Мне навсегда потребовалось понять, что GuidConstraint ограничивает реальный Гид, если это имеет какой-то смысл.:)
Здесь то, с чем я закончил, который принимает любой тип данных (а не просто строку), немного быстрее (я думаю), и содержит меньше, если блочное вложение.
public class GuidConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
object value;
if (!values.TryGetValue(parameterName, out value)) return false;
if (value is Guid) return true;
var stringValue = Convert.ToString(value);
if (string.IsNullOrWhiteSpace(stringValue)) return false;
Guid guidValue;
if (!Guid.TryParse(stringValue, out guidValue)) return false;
if (guidValue == Guid.Empty) return false;
return true;
}
}
Ответ 5
+1 @kazimanzurrashid. Кажется, на месте.
Я дам альтернативу тем, у кого нет С# 4.0, из которых Guid.TryParse является частью. Там другая альтернатива Regex, но вероятно, не стоит беспокоить.
public class GuidConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (values.ContainsKey(parameterName))
{
string stringValue = values[parameterName] as string;
if (!string.IsNullOrEmpty(stringValue))
{
//replace with Guid.TryParse when available.
try
{
Guid guid = new Guid(stringValue);
return true;
}
catch
{
return false;
}
}
}
return false;
}
}
Ответ 6
Я обнаружил, что при условии, что тип является причиной Guid при использовании таких вещей, как @Html.RouteLink(...) и в тестах маршрутизации, где URL-адрес предоставляется в виде строки. Ниже приведенный ниже код подходит для этих ситуаций. Использование приведенных выше примеров кода вызвало проблемы в моих представлениях и/или тестах, это ниже прекрасно работает.
public class GuidConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var value = values[parameterName];
if (value == null) return false;
var stringValue = value.ToString();
if (string.IsNullOrEmpty(stringValue)) return false;
Guid guidValue;
return Guid.TryParse(stringValue, out guidValue) && (guidValue != Guid.Empty);
}
}