2009-03-07 9 views
62

È possibile utilizzare HtmlHelper in un controller, ad esempio per ottenere il metodo TextBox (...)? Non che io non possa scrivere l'html che genera me stesso, ma voglio solo capire come funziona così posso creare la soluzione migliore.Utilizzo di HtmlHelper in un controller

risposta

39

Ecco un esempio tratto dal this:

var h = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView("omg"), new ViewDataDictionary(), new TempDataDictionary()), new ViewPage()); 
h.TextBox("myname"); 

Si noti che questo è un hack, si può fare, ma non credo che ci sia una buona ragione per fare questo ...

+3

non credo che sia una cosa fantastica da fare sia , ma sto usando i controlli di griglia di Telerik che usano AJAX, e quando si usa AJAX, ClientTemplate per una colonna deve essere testo pre-renderizzato - non sarà in grado di res olve l'azione sul client. Questa è la ragione per cui ho cercato, comunque. Preferirei che i controlli non funzionassero in questo modo, ma se è il prezzo che pago per aver controllato anni luce meglio di qualsiasi cosa potrei fare, allora è qualcosa su cui lavorerò. –

+1

questo esempio non è valido ora – Anubis

+0

@Anubis: cosa intendi con 'ora'? ASP.NET MVC 3? –

7

Il HtmlHelper è parte del meccanismo di visualizzazione in base alla progettazione e deve essere considerato separato per le parti del controller e del modello di MVC. Non sono sicuro del motivo per cui si desidera generare controlli all'interno del controller poiché il ruolo è quello di fornire i dati alla vista per il rendering.

Non sto dicendo che non è possibile raggiungerlo, ma per un buon design sarebbe meglio.

Puoi spiegare cosa stai cercando di ottenere e quindi potremmo considerarlo in un "modo MVC"?

+1

Lo stavo usando come un modo per generare l'html del controllo basato su una selezione utente in un modulo Ajax. Cercando di ottenere lo stesso concetto dei moduli Rails RJS. Sebbene la soluzione fornita abbia funzionato, sono d'accordo sul fatto che questa non è la soluzione più pulita e probabilmente finirò per rendere tutto ciò lato client, dopo tutto. – Gil

30

È possibile utilizzare metodo come questo:

public static HtmlHelper GetHtmlHelper(this Controller controller) 
{ 
    var viewContext = new ViewContext(controller.ControllerContext, new FakeView(), controller.ViewData, controller.TempData, TextWriter.Null); 
    return new HtmlHelper(viewContext, new ViewPage()); 
} 

public class FakeView : IView 
{ 
    public void Render(ViewContext viewContext, TextWriter writer) 
    { 
     throw new InvalidOperationException(); 
    } 
} 
+0

pensa di aggiungere "using System.Web.Mvc.Html;" per ottenere tutte le estensioni HtmlHelper (questo è con MVC 3) – Dragouf

+4

Un buon modo per usare htmlhelper nel controller con mvc 3 è chiamare il metodo Parziale per rendere html di una vista (per esempio per usare la vista del rasoio come modello html email) – Dragouf

+0

Questo è esattamente quello che stavo cercando, funziona come un fascino. Grazie per aver condiviso questo codice. – ViRuSTriNiTy

4
using System.Web.Mvc; 
using System.Web.Mvc.Html; 

var h = new HtmlHelper<Effort>(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "omg"), new ViewDataDictionary(), new TempDataDictionary(), new StringWriter()), new ViewPage()); 

h.DisplayFor(e => Model.Efforts[i].Content.Offer.Price1.Value) 
+1

questo mi ha aiutato. –

+0

l'unico che ha funzionato davvero in una volta qui – matthy

0

Se qualcuno sta cercando di fare questo da senza un controller (come quando test di unità), ci sono altri problemi da affrontare, come molti di questi metodi (che so, non erano uno scenario di test, ma per quello scenario) lanciavano eccezioni Null (ViewContext.ScopeCache). Si può vedere questo dal seguente (nota tutti questi modi richiedono un'istanza ViewContext a formarsi, che è uno dei parametri che si inserisce nel costruttore dell'istanza HtmlHelper, così via quell'oggetto):

viewContext.UnobtrusiveJavaScriptEnabled = false; 

Semplicemente impostando quel valore si genera un'eccezione con molti di questi metodi, ma il problema è stato risolto per me by this answer, vedere come ottiene un HtmlHelper (vedere anche here).

0
  • utilizzando System.Web.Mvc;
  • utilizzando System.Web.Mvc.Html;

    HtmlHelper helper = new HtmlHelper(new ViewContext(ControllerContext, new   WebFormView(ControllerContext, "Index"), new ViewDataDictionary(), new TempDataDictionary(), new System.IO.StringWriter()), new ViewPage()); 
    
0

Per .NET Core 2 MVC: https://github.com/aspnet/Mvc/issues/7321

using Microsoft.AspNetCore.Mvc; 
using Microsoft.AspNetCore.Mvc.Infrastructure; 
using Microsoft.AspNetCore.Mvc.ModelBinding; 
using Microsoft.AspNetCore.Mvc.Rendering; 
using Microsoft.AspNetCore.Mvc.Routing; 
using Microsoft.AspNetCore.Mvc.ViewEngines; 
using Microsoft.AspNetCore.Mvc.ViewFeatures; 
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; 
using Microsoft.Extensions.Options; 
using System.IO; 
using System.Text.Encodings.Web; 
using System.Threading.Tasks; 


    public class HelperGenerator 
    { 
     private readonly IHtmlGenerator _htmlGenerator; 
     private readonly ICompositeViewEngine _compositeViewEngine; 
     private readonly IModelMetadataProvider _modelMetadataProvider; 
     private readonly IViewBufferScope _viewBufferScope; 
     private readonly IActionContextAccessor _actionContextAccessor; 
     private readonly HtmlHelperOptions _htmlHelperOptions; 

     public HelperGenerator(IHtmlGenerator htmlGenerator, ICompositeViewEngine compositeViewEngine, IModelMetadataProvider modelMetadataProvider, IViewBufferScope viewBufferScope, IActionContextAccessor actionContextAccessor, IOptions<MvcViewOptions> options) 
     { 
      _htmlGenerator = htmlGenerator; 
      _compositeViewEngine = compositeViewEngine; 
      _modelMetadataProvider = modelMetadataProvider; 
      _viewBufferScope = viewBufferScope; 
      _actionContextAccessor = actionContextAccessor; 
      _htmlHelperOptions = options.Value.HtmlHelperOptions; 
     } 
     public IHtmlHelper HtmlHelper(ViewDataDictionary ViewData, ITempDataDictionary TempData) 
     { 
      var helper = new HtmlHelper(_htmlGenerator, _compositeViewEngine, _modelMetadataProvider, _viewBufferScope, HtmlEncoder.Default, UrlEncoder.Default); 
      var viewContext = new ViewContext(_actionContextAccessor.ActionContext, 
       new FakeView(), 
       ViewData, 
       TempData, 
       TextWriter.Null, 
       _htmlHelperOptions); 
      helper.Contextualize(viewContext); 
      return helper; 
     } 
     private class FakeView : IView 
     { 
      public string Path => "View"; 

      public Task RenderAsync(ViewContext context) 
      { 
       return Task.FromResult(0); 
      } 
     } 
    } 

Assicurati di registrare nel settore dei servizi:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); 
Problemi correlati