Domanda

Sto scrivendo la mia estensione HtmlHelper per ASP.NET MVC:

public static string CreateDialogLink (this HtmlHelper htmlHelper, string linkText, 
                                      string contentPath)
        {
            // fix up content path if the user supplied a path beginning with '~'
            contentPath = Url.Content(contentPath);  // doesn't work (see below for why)

            // create the link and return it
            // .....
        };

Dove sto riscontrando problemi sta provando ad accedere a UrlHelper da in la definizione del mio HtmlHelper. Il problema è che il modo in cui normalmente si accede a HtmlHelper (tramite Html.MethodName(...)) avviene tramite una proprietà nella vista. Questo non è disponibile per me ovviamente con la mia classe di estensione.

Questo è il codice sorgente MVC effettivo per ViewMasterPage (a partire da Beta) - che definisce Html e Url.

public class ViewMasterPage : MasterPage
    {
        public ViewMasterPage();

        public AjaxHelper Ajax { get; }
        public HtmlHelper Html { get; }
        public object Model { get; }
        public TempDataDictionary TempData { get; }
        public UrlHelper Url { get; }
        public ViewContext ViewContext { get; }
        public ViewDataDictionary ViewData { get; }
        public HtmlTextWriter Writer { get; }
    }

Voglio poter accedere a queste proprietà all'interno di un HtmlHelper.

Il migliore che ho trovato è questo (inserire all'inizio del CreateDialogLink metodo)

HtmlHelper Html = new HtmlHelper(htmlHelper.ViewContext, htmlHelper.ViewDataContainer);
UrlHelper Url = new UrlHelper(htmlHelper.ViewContext.RequestContext);

Mi manca un altro modo per accedere alle istanze <=> e <=> esistenti o devo davvero crearne una nuova? Sono sicuro che non c'è molto overhead ma preferirei usare quelli preesistenti se posso.

È stato utile?

Soluzione

Prima di porre questa domanda avevo esaminato un po 'del codice sorgente MVC, ma evidentemente mi mancava questo, ed è così che lo fanno per l'helper Image.

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "The return value is not a regular URL since it may contain ~/ ASP.NET-specific characters")]
        public static string Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
            if (String.IsNullOrEmpty(imageRelativeUrl)) {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
            }

            UrlHelper url = new UrlHelper(helper.ViewContext);
            string imageUrl = url.Content(imageRelativeUrl);
            return Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing);
        }

Sembra che l'istanza di un nuovo UrlHelper sia l'approccio corretto dopo tutto. Questo è abbastanza buono per me.


Aggiornamento: codice RTM da ASP.NET MVC v1.0 Source Code è leggermente diverso come indicato nei commenti.

File: MVC \ src \ MvcFutures \ Mvc \ ImageExtensions.cs

 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "1#", Justification = "The return value is not a regular URL since it may contain ~/ ASP.NET-specific characters")]
        public static string Image(this HtmlHelper helper, string imageRelativeUrl, string alt, IDictionary<string, object> htmlAttributes) {
            if (String.IsNullOrEmpty(imageRelativeUrl)) {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "imageRelativeUrl");
            }

            UrlHelper url = new UrlHelper(helper.ViewContext.RequestContext);
            string imageUrl = url.Content(imageRelativeUrl);
            return Image(imageUrl, alt, htmlAttributes).ToString(TagRenderMode.SelfClosing);
        }

Altri suggerimenti

Ho riscontrato un problema simile e ho deciso che sarebbe stato più semplice chiamare UrlHelper nella vista e passare l'output alla mia estensione HtmlHelper. Nel tuo caso sembrerebbe:

<%= Html.CreateDialogLink( "text", Url.Content( "~/...path.to.content" ) ) %>

Se vuoi accedere ai metodi di estensione sull'HtmlHelper esistente che viene passato alla tua classe, dovresti solo importare System.Web.Mvc.Html nel tuo file di codice sorgente e avrai accesso ad essi (è lì le classi di estensione sono definite). Se vuoi un UrlHelper, dovrai creare un'istanza in quanto l'HtmlHelper che stai ricevendo non ha un handle per ViewPage da cui proviene.

Se è necessario creare un UrlHelper in una classe di utilità, è possibile effettuare le seguenti operazioni:

string url = " ~ / content / images / foo.jpg " ;;

  var urlHelper = new UrlHelper(new RequestContext(
                  new HttpContextWrapper(HttpContext.Current), 
                  new RouteData()), RouteTable.Routes);

  string absoluteUrl = urlHelper.Content(url);

Ciò consente di utilizzare il routing o "~ espansione" lontano da un contesto MVC.

Bene, puoi sempre passare l'istanza della pagina al metodo di estensione. Penso che sia un modo molto migliore per farlo rispetto alla creazione di nuove istanze nel tuo metodo.

Puoi anche definire questo metodo su una classe che deriva da MasterPage / ViewMasterPage e quindi derivare la pagina da quello. In questo modo, hai accesso a tutte le proprietà dell'istanza e non devi passarle in giro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top