1

Ich baue das Front-End einer Anwendung neu und aufgrund seiner Komplexität muss ich auf der bestehenden Legacy-Business-Schicht arbeiten. Als Ergebnis haben wir Dinge, die "Nachrichten" und "Dokumente" genannt werden, aber in Wirklichkeit sind beide "Dokumente", wo sie gespeichert sind.Url.Action Ergebnis wird nicht aufgelöst mit Route Attribut

Ich habe eine DocumentsController gemacht, die alles gut behandelt, schlägt eine [Route("News/{action=index}")] und [Route("Documents/{action=index}")] auf dem Controller ermöglicht es mir, den Controller als entweder News oder Dokumente beziehen. So weit, ist es gut. Das Anzeigen eines bestimmten Dokuments unter Verwendung eines einzelnen ActionResult mit den Attributen [Route("Documents/View/{id}"] und [Route("News/View/{id}"] funktioniert auch gut. Allerdings bekomme ich ein Problem, wenn ich versuche, etwas anderes als id als Parameter zu verwenden, aber nur für den Nachrichtenteil.

Meine ActionResult Methode hat die folgende Definition

[Route("Documents/Download/{documentGuid}/{attachmentGuid}")] 
[Route("News/Download/{documentGuid}/{attachmentGuid}")] 
public ActionResult Download(Guid documentGuid, Guid attachmentGuid) 
... 

Und mein Blick hat im Anschluss an die Sie den Link

<a href="@Url.Action("Download", "Documents", new { documentGuid = Model.Id, attachmentGuid = attachment.AttachmentId })">Download</a> 
Diese

erhalten einen Link ähnlich site/Documents/Download/guid/guid perfekt jedes Mal, wenn ich „Dokumente“ haben Als der Controller, aber wenn ich "News" dort stelle, erhalte ich eine URL, die Querystring ähnlich den site/News/Download?guid&guid Parametern verwendet und in ein 404 aufgelöst wird. Wenn ich dann manuell die Querystring-Tokens entferne und die URL man formatiere Natürlich wird es sich gut lösen.

Was läuft hier falsch, ist etwas widersprüchlich, dass ich vermisse?

Antwort

1

Beim Suchen einer Route nach einer eingehenden Anfrage ermittelt das Routing anhand der URL, welche Route übereinstimmt. Ihre eingehenden URLs sind eindeutig und funktionieren daher einwandfrei.

Wenn Sie jedoch eine Route zum Generieren suchen, verwendet MVC die Routenwerte, um zu bestimmen, welche Route übereinstimmt. Die Literalsegmente in der URL (News/Download/) werden für diesen Teil des Prozesses vollständig ignoriert.

Bei Verwendung des Attribut-Routing werden die Routenwerte vom Controller-Namen und Aktionsnamen der von Ihnen eingerichteten Methode abgeleitet. Also, in beiden Fällen Ihre Route Werte sind:

| Key    | Value   | 
|-----------------|-----------------| 
| controller  | Documents  | 
| action   | Download  | 
| documentGuid | <some GUID>  | 
| attachmentGuid | <some GUID>  | 

Mit anderen Worten: Ihre Route Werte sind nicht eindeutig. Daher gewinnt immer die erste Übereinstimmung in der Routentabelle.

Um dieses Problem zu umgehen, können Sie benannte Routen verwenden.

[Route("Documents/Download/{documentGuid}/{attachmentGuid}", Name = "Documents")] 
[Route("News/Download/{documentGuid}/{attachmentGuid}", Name = "News")] 
public ActionResult Download(Guid documentGuid, Guid attachmentGuid) 
... 

Dann lösen Sie die URLs mit @Url.RouteUrl oder @Html.RouteLink.

@Html.RouteLink("Download", "News", new { controller = "Documents", action = "Download", documentGuid = Model.Id, attachmentGuid = attachment.AttachmentId }) 

Oder

<a href="@Url.RouteUrl("News", new { controller = "Documents", action = "Download", documentGuid = Model.Id, attachmentGuid = attachment.AttachmentId })">Download</a> 
+0

Dank für die ausführliche Antwort, das war genau das Problem und eine Arbeitslösung:) – Perry

1

Die Parameter Ihrer Url.Action sind der Name des Controllers und der Name der Aktion, es funktioniert nur für Dokumente, weil Ihre Route dann zufällig den richtigen Namen entspricht. Wenn Sie eine bestimmte Route verwenden möchten, müssen Sie Ihre Routen benennen und dann eine der Methoden verwenden, die den Namen der Route verwendet, um sie zu erstellen.