web-dev-qa-db-fra.com

Le routage d'attributs ne fonctionne pas dans les zones

Scénario: J'ai une zone Formulaires dans mon site ASP.NET MVC 5.

J'essaie de rediriger vers l'action de détails qui utilise une route personnalisée définie à l'aide de la nouvelle fonctionnalité de routage d'attributs.

Le RedirectToAction:

return RedirectToAction("Details", new { slug });

L'action vers laquelle je redirige:

[HttpGet]
[Route("forms/{slug}")]
public ActionResult Details(string slug)
{
    var form = FormRepository.Get(slug);

    ...

    return View(model);
}

Je m'attendrais à une redirection vers http://localhost/forms/my-slug mais à la place, l'application me redirige vers http://localhost/Forms/Details?slug=my-slug.

Cela signifie que le routage d'attributs ne fonctionne pas.

Comment résoudre ce problème?

J'ai ajouté les routes.MapMvcAttributeRoutes (); ligne vers mon RouteConfig:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Et voici mon Application_Start ():

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}
45
Thomas Stock

Vous combinez probablement le routage basé sur les conventions avec le routage d'attributs, et vous devez enregistrer vos zones après avoir mappé les routes d'attributs .

La ligne

AreaRegistration.RegisterAllAreas();

devrait être appelé APRÈS cette ligne:

routes.MapMvcAttributeRoutes();

L'explication (de http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx#route-areas ):

Si vous utilisez à la fois des zones avec des attributs de route et des zones avec des routes basées sur des conventions (définies par une classe AreaRegistration), vous devez vous assurer que l'enregistrement de zone se produit après la configuration des routes d'attributs MVC, mais avant que la route par défaut basée sur les conventions ne soit ensemble. La raison en est que l'enregistrement de l'itinéraire doit être ordonné du plus spécifique (attributs) au plus général (enregistrement de zone) au brouillard générique (l'itinéraire par défaut) pour éviter que les itinéraires génériques ne "masquent" des itinéraires plus spécifiques en faisant correspondre les demandes entrantes trop tôt dans le pipeline.

Lorsque vous créez un site Web asp.net mvc vide, ajoutez une zone et commencez à utiliser le routage d'attributs, vous rencontrerez ce problème car l'action "Ajouter une zone" dans Visual Studio ajoute l'appel RegisterAllAreas dans votre Application_Start, avant la configuration de l'itinéraire.

Solution alternative

Vous n'avez peut-être pas l'intention de continuer à utiliser le routage basé sur les conventions et préférez utiliser uniquement le routage d'attributs. Dans ce cas, vous pouvez simplement supprimer le fichier FormsAreaRegistration.cs.

89
Thomas Stock

Déplacer le AreaRegistration.RegisterAllAreas () vers RouteConfig.cs n'était pas suffisant pour moi. J'ai également dû utiliser le paramètre AreaPrefix pour l'attribut RouteArea:

//Use the named parameter "AreaPrefix"
[RouteArea("AreaName", AreaPrefix = "area-name-in-url")]
[RoutePrefix("controller-name-in-url")]
public class SampleController : Controller
{
    [Route("{actionParameter}")]
    public ActionResult Index(string actionParameter)
    {
        return View();
    }
}

Edit: À un moment donné, je suis tombé sur un exemple de solution de Microsoft qui a bien montré comment gérer le routage d'attributs. Il a également montré quelques bons exemples de la façon de traduire un SelectList en un tableau de input[type="radio"] éléments et faire de même avec un tableau de input[type="checkbox"] articles (si je me souviens bien). Cet exemple de solution est probablement une meilleure réponse à cette question - ainsi que de donner de bons exemples sur l'affichage des boutons radio et des éléments de case à cocher. Si quelqu'un connaît cet exemple de solution, veuillez ajouter un commentaire avec un lien vers celui-ci.

38