2009-03-07 37 views
62

Có thể sử dụng HtmlHelper trong bộ điều khiển, ví dụ để lấy phương thức TextBox (...) không? không phải là tôi không thể viết html mà nó tạo ra bản thân mình, nhưng tôi chỉ muốn hiểu cách làm việc này để tôi có thể tạo ra giải pháp tốt nhất.Sử dụng HtmlHelper trong Bộ điều khiển

Trả lời

39

Dưới đây là một ví dụ chuyển thể từ this:

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

Lưu ý rằng đây là một hack, nó có thể được thực hiện nhưng tôi không nghĩ rằng có bất kỳ lý do chính đáng để làm điều này ...

+3

Tôi không nghĩ rằng đó là một điều tuyệt vời để làm một trong hai , nhưng tôi đang sử dụng các điều khiển lưới Telerik sử dụng AJAX, và khi sử dụng AJAX, ClientTemplate cho một cột phải được hiển thị trước văn bản - nó sẽ không thể khôi phục olve hành động trên máy khách. Đó là lý do _my_ để tìm kiếm điều này, ở mức nào. Tôi thích các điều khiển không hoạt động theo cách này, nhưng nếu đó là cái giá tôi phải trả cho việc kiểm soát ánh sáng tốt hơn mọi thứ tôi có thể làm, thì đó là thứ tôi sẽ làm việc. –

+1

ví dụ này không hợp lệ ngay bây giờ – Anubis

+0

@Anubis: ý của bạn là gì 'bây giờ'? ASP.NET MVC 3? –

7

Các HtmlHelper là một phần của cơ chế Xem theo thiết kế và cần được xem xét riêng biệt với phần Bộ điều khiển và Mô hình của MVC. Tôi không chắc chắn lý do tại sao bạn sẽ muốn tạo ra các điều khiển bên trong bộ điều khiển vì vai trò của nó là cung cấp Dữ liệu cho khung nhìn để hiển thị.

Tôi không nói rằng bạn không thể đạt được nó, nhưng đối với thiết kế tốt nó sẽ tốt hơn.

Bạn có thể giải thích những gì bạn đang cố gắng đạt được và sau đó chúng ta có thể xem xét việc thực hiện nó theo cách "MVC" không?

+1

Tôi đã sử dụng nó như một cách để tạo html của điều khiển dựa trên lựa chọn của người dùng ở dạng ajax. Đang cố gắng để có được khái niệm tương tự như Rails RJS hình thức. Mặc dù giải pháp được cung cấp đã hoạt động nhưng tôi đồng ý rằng đây không phải là giải pháp rõ ràng nhất và cuối cùng tôi sẽ làm cho tất cả khách hàng trở thành tất cả. – Gil

30

Bạn có thể sử dụng phương pháp như thế này:

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

suy nghĩ để thêm "using System.Web.Mvc.Html;" Để có được tất cả phần mở rộng HtmlHelper (đây là với MVC 3) – Dragouf

+4

Cách tốt nhất để sử dụng htmlhelper trong bộ điều khiển với mvc 3 là gọi phương thức một phần để hiển thị html của chế độ xem (ví dụ: sử dụng dạng xem dao cạo dạng email html mẫu) – Dragouf

+0

Đây là chính xác những gì tôi đang tìm kiếm, hoạt động như một sự quyến rũ. Cảm ơn bạn đã chia sẻ mã này. – 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

điều này đã giúp tôi. –

+0

người duy nhất thực sự làm việc trong một thời gian ở đây – matthy

0

Nếu ai đó đang cố gắng để làm điều này từ mà không có một bộ điều khiển (như khi kiểm tra đơn vị), có những vấn đề hơn nữa để đối phó với, như nhiều những phương pháp này (mà tôi biết, không phải là một kịch bản thử nghiệm, nhưng đối với kịch bản đó) đã ném ngoại lệ Null (ViewContext.ScopeCache). Bạn có thể thấy điều này bằng cách như sau (lưu ý tất cả các cách đòi hỏi một trường hợp ViewContext được hình thành, đó là một trong những thông số bạn chèn vào constructor của instance HtmlHelper, vân vân đối tượng đó):

viewContext.UnobtrusiveJavaScriptEnabled = false; 

Đơn giản chỉ cần thiết lập giá trị đó ném một ngoại lệ với nhiều phương pháp này, nhưng vấn đề đã được sửa cho tôi by this answer, xem cách anh ta nhận được một HtmlHelper (xem thêm here).

0
  • bằng System.Web.Mvc;
  • sử dụng 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

Đối với 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); 
      } 
     } 
    } 

Hãy chắc chắn để đăng ký dịch vụ:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); 
Các vấn đề liên quan