MVC RouteUrl не учитывает атрибут исключения - PullRequest
2 голосов
/ 19 июня 2011

(я использую ASP.NET MVC 2.)

Как исключить определенные свойства из перехода в строку запроса при использовании Url.RouteUrl(object)?

В частности, в моем объекте Modelкоторый передается в мой View, у меня есть массив строк (технически IEnumerable ), который я хочу исключить.

Я думал, что атрибут Bind с Exclude должен был делать это, но это не такт работа.Я пытался добавить [Bind(Exclude = "Sizes")] в свой класс, но продолжаю получать URL, которые выглядят так:

http://localhost/?Sizes=System.String[]

Ответы [ 2 ]

2 голосов
/ 23 июня 2011

Методы расширения и Отражение на помощь!

/// <summary>
/// Add UrlHelper extension methods that construct outgoing URL's but 
/// remove route values that are excluded by the Bind attribute's 
/// Include or Exclude.  The methods to mirror are those that take an 
/// object as an argument:
///
/// public string Action(string actionName, object routeValues);
/// public string Action(string actionName, string controllerName
///                    , object routeValues);
/// public string Action(string actionName, string controllerName
///                    , object routeValues, string protocol);
///
/// public string RouteUrl(object routeValues);
/// public string RouteUrl(string routeName, object routeValues);
/// public string RouteUrl(string routeName, object routeValues
///                      , string protocol);
/// </summary>
public static class UrlHelperExtensions
{
    public static string Action(this UrlHelper helper, string actionName
                                , object routeValues, bool onlyBoundValues)
    {
        RouteValueDictionary finalRouteValues =
             new RouteValueDictionary(routeValues);

        if (onlyBoundValues)
        {
            RemoveUnboundValues(finalRouteValues, routeValues);
        }

        // Internally, MVC calls an overload of GenerateUrl with
        // hard-coded defaults.  Since we shouldn't know what these
        // defaults are, we call the non-extension equivalents.
        return helper.Action(actionName, routeValues);
    }

    public static string Action(this UrlHelper helper, string actionName
                                , string controllerName, object routeValues
                                , bool onlyBoundValues)
    {
        RouteValueDictionary finalRouteValues =
             new RouteValueDictionary(routeValues);

        if (onlyBoundValues)
        {
            RemoveUnboundValues(finalRouteValues, routeValues);
        }

        return helper.Action(actionName, controllerName, finalRouteValues);
    }

    public static string Action(this UrlHelper helper, string actionName
                                , string controllerName, object routeValues
                                , string protocol, bool onlyBoundValues)
    {
        RouteValueDictionary finalRouteValues =
             new RouteValueDictionary(routeValues);

        if (onlyBoundValues)
        {
            RemoveUnboundValues(finalRouteValues, routeValues);
        }

        return helper.Action(actionName, controllerName
                              , finalRouteValues, protocol);
    }

    public static string RouteUrl(this UrlHelper helper, object routeValues
                                  , bool onlyBoundValues)
    {
        RouteValueDictionary finalRouteValues =
             new RouteValueDictionary(routeValues);
        if (onlyBoundValues)
        {
            RemoveUnboundValues(finalRouteValues, routeValues);
        }
        return helper.RouteUrl(finalRouteValues);
    }

    public static string RouteUrl(this UrlHelper helper, string routeName
                                  , object routeValues, bool onlyBoundValues)
    {
        RouteValueDictionary finalRouteValues =
             new RouteValueDictionary(routeValues);
        if (onlyBoundValues)
        {
            RemoveUnboundValues(finalRouteValues, routeValues);
        }
        return helper.RouteUrl(routeName, finalRouteValues);
    }

    public static string RouteUrl(this UrlHelper helper, string routeName
                                  , object routeValues, string protocol
                                  , bool onlyBoundValues)
    {
        RouteValueDictionary finalRouteValues =
             new RouteValueDictionary(routeValues);

        if (onlyBoundValues)
        {
            RemoveUnboundValues(finalRouteValues, routeValues);
        }

        return helper.RouteUrl(routeName, finalRouteValues, protocol);
    }

    /// <summary>
    /// Reflect into the routeValueObject and remove any keys from
    /// routeValues that are not bound by the Bind attribute
    /// </summary>
    private static void RemoveUnboundValues(RouteValueDictionary routeValues
                                            , object source)
    {
        if (source == null)
        {
            return;
        }

        var type = source.GetType();

        BindAttribute b = null;

        foreach (var attribute in type.GetCustomAttributes(true))
        {
            if (attribute is BindAttribute)
            {
                b = (BindAttribute)attribute;
                break;
            }
        }

        if (b == null)
        {
            return;
        }

        foreach (var property in type.GetProperties())
        {
            var propertyName = property.Name;
            if (!b.IsPropertyAllowed(propertyName))
            {
                routeValues.Remove(propertyName);
            }
        }
    }
}
1 голос
/ 19 июня 2011

Будут использованы все свойства анонимного объекта и AFAIK нет возможности исключить некоторые.Атрибут [Bind] используется в аргументах действия контроллера для указания свойств связывателя модели, которые следует исключить или включить из привязки модели, но не для создания URL-адресов.Вам может потребоваться указать свойства, которые вы хотите по одному:

Url.RouteUrl(new { 
    Prop1 = Model.Prop1, 
    Prop2 = Model.Prop2, 
    action = "SomeAction",
    controller = "SomeController"
})

или включить только идентификатор:

Url.RouteUrl(new { 
    id = Model.Id, 
    action = "SomeAction",
    controller = "SomeController"
})

и иметь целевое действие контроллера для использования этого идентификатора, чтобыполучить модель из некоторого постоянного хранилища данных.

...