2009-03-07 11 views
62

Ist es möglich, HtmlHelper in einem Controller zu verwenden, um beispielsweise die TextBox (...) -Methode zu erhalten? Nicht, dass ich nicht das HTML schreiben kann, das es selbst erzeugt, aber ich möchte nur verstehen, wie das funktioniert, damit ich die beste Lösung erstellen kann.Verwenden von HtmlHelper in einem Controller

Antwort

39

Hier ist ein Beispiel von this angepasst:

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

Beachten Sie, dass dies ein Hack ist, es kann getan werden, aber ich glaube nicht, dass es ein guter Grund, dies zu tun ...

+3

Ich glaube nicht, dass es eine fantastische Sache ist entweder zu tun , aber ich verwende Telerik Grid-Steuerelemente, die AJAX verwenden, und wenn AJAX verwendet wird, muss das ClientTemplate für eine Spalte vorgerenderter Text sein - es wird nicht res sein können olve die Aktion auf dem Client. Das ist jedenfalls mein Grund, um nachzusehen. Ich würde es bevorzugen, wenn die Steuerung nicht so funktioniert, aber wenn es der Preis ist, den ich dafür bezahle, Lichtjahre besser kontrollieren zu können, als alles, was ich tun kann, dann ist es etwas, woran ich arbeiten werde. –

+1

dieses Beispiel ist jetzt nicht gültig – Anubis

+0

@Anubis: was meinst du mit 'jetzt'? ASP.NET MVC 3? –

7

Die HtmlHelper ist von Entwurf her Teil des View-Mechanismus und sollte getrennt von den Controller- und Modellteilen von MVC betrachtet werden. Ich bin mir nicht sicher, warum Sie Kontrollen innerhalb des Controllers generieren möchten, da es die Aufgabe ist, die Daten zum Rendern an die Ansicht zu liefern.

Ich sage nicht, dass Sie es nicht erreichen können, aber für gutes Design wäre es besser.

Können Sie erklären, was Sie erreichen möchten, und dann könnten wir es auf "MVC-Weise" machen?

+1

Ich benutzte es als eine Möglichkeit, das HTML des Steuerelements basierend auf einer Benutzerauswahl in einem AJAX-Formular zu generieren. Versuchen, das gleiche Konzept wie Rails RJS Formulare zu erhalten. Obwohl die gelieferte Lösung funktioniert, stimme ich zu, dass dies nicht die sauberste Lösung ist, und ich werde wahrscheinlich am Ende alle Client-Seite schließlich machen. – Gil

30

Sie können Methode wie folgt verwenden:

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

denke, um "using System.Web.Mvc.Html;" Um alle HtmlHelper-Erweiterung zu bekommen (dies ist mit MVC 3) – Dragouf

+4

Eine nette Möglichkeit, HTML-Helper in Controller mit MVC 3 zu verwenden, ist Teilmethode aufrufen, um HTML einer Ansicht zu rendern (zum Beispiel Rasierer Ansicht als Vorlage HTML-E-Mail) – Dragouf

+0

Dies ist genau das, wonach ich suchte, wirkt wie ein Zauber. Vielen Dank für die Freigabe dieses Codes. – 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

das hat mir geholfen. –

+0

der einzige, der hier wirklich einmal funktioniert hat – matthy

0

Wenn jemand dies versucht, von ohne Controller zu tun (wie wenn Unit-Tests), gibt es weitere Probleme zu behandeln, wie viele Diese Methoden (von denen ich weiß, dass sie kein Testszenario waren, sondern für dieses Szenario) haben Null-Ausnahmen ausgelöst (ViewContext.ScopeCache). Sie können dies sehen durch die folgende (beachten Sie alle diese Möglichkeiten erfordern eine ViewContext Instanz gebildet werden, was einer der Parameter, die Sie in den Konstruktor der Htmlhelper Instanz einlegen, so auf das Objekt):

viewContext.UnobtrusiveJavaScriptEnabled = false; 

Einfach diesen Wert zu setzen, löst bei vielen dieser Methoden eine Ausnahme aus, aber das Problem wurde für mich behoben by this answer, sehen Sie, wie er eine HtmlHelper bekommt (siehe auch here).

0
  • mit System.Web.Mvc;
  • mit 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

Für .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); 
      } 
     } 
    } 

Stellen Sie sicher, in Dienste registrieren:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); 
Verwandte Themen