Razor로 일반 @helper 메서드를 만들 수 있습니까?


89

Razor에서 다음과 같은 도우미를 작성하려고합니다.

@helper DoSomething<T, U>(Expression<Func<T, U>> expr) where T : class

불행히도 파서 <T는 이것이 HTML 요소의 시작 이라고 생각 하고 구문 오류로 끝납니다. 일반 메서드 인 Razor로 도우미를 만들 수 있습니까? 그렇다면 구문은 무엇입니까?


현재 MVC 4 릴리스에서는 아직 수정되지 않았습니다. :(
Alex Dresko 2012 년

1
이것이 VS2012에서 어떻게 해결되지 않습니까?
Alex Dresko 2010 년

7
맙소사, 이것이 추가되기를 기다릴 수 없습니다. 나는 이것이 우선 순위 목록의 " 어제 구현하기 "주변 어딘가에 있기를 바랍니다 . 부분적으로 주제에서 벗어 났지만 이와 함께 생성 된 클래스는 static구현 세부 사항이 금지하지 않는 한. 이유 존재, 하나는 사용할 수 있습니다 일반 확장 헬퍼 :@helper Foo<T>(this T o) where T : IBar { }
댄 Lugg

답변:


52

아니요, 현재는 불가능합니다. 대신 일반 HTML 도우미를 작성할 수 있습니다.

public static MvcHtmlString DoSomething<T, U>(
    this HtmlHelper htmlHelper, 
    Expression<Func<T, U>> expr
) where T : class
{
    ...
}

그리고:

@(Html.DoSomething<SomeModel, string>(x => x.SomeProperty))

또는 모델을 첫 번째 일반 인수로 타겟팅하는 경우 :

public static MvcHtmlString DoSomething<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expr
) where TModel : class
{
    ...
}

다음과 같이 호출 할 수 있습니다.

@Html.DoSomething(x => x.SomeProperty)

10
바라건대 이것은 향후 버전의 Razor 도우미에 추가하는 것입니다. 전통적인 도우미의 가독성은 @helper 구문보다 훨씬 낮습니다.
mkedobbs 2011 년

2
네 동의했습니다. 이전 방법으로 되 돌리는 것은 짜증 스러울뿐만 아니라 도우미를 임의로 분할합니다!
George R

127

이것은 이다 와 헬퍼 파일 안에 달성 할 수 @functions구문하지만 당신이 원하는 경우에 당신이 언급하는 면도칼 스타일의 가독성 또한 HTML의 적합과 끝을 할 수있는 일반 도우미를 호출해야합니다.

도우미 파일의 함수는 정적이므로 해당 메서드를 사용하려는 경우 페이지에서 HtmlHelper 인스턴스를 계속 전달해야합니다.

예 : Views \ MyView.cshtml :

@MyHelper.DoSomething(Html, m=>m.Property1)
@MyHelper.DoSomething(Html, m=>m.Property2)
@MyHelper.DoSomething(Html, m=>m.Property3)

App_Code \ MyHelper.cshtml :

@using System.Web.Mvc;
@using System.Web.Mvc.Html;
@using System.Linq.Expressions;
@functions
{
    public static HelperResult DoSomething<TModel, TItem>(HtmlHelper<TModel> html, Expression<Func<TModel, TItem>> expr)
    {
        return TheThingToDo(html.LabelFor(expr), html.EditorFor(expr), html.ValidationMessageFor(expr));
    }
}
@helper TheThingToDo(MvcHtmlString label, MvcHtmlString textbox, MvcHtmlString validationMessage)
{
    <p>
        @label
        <br />
        @textbox
        @validationMessage
    </p>
}
...

이것은 완벽 해요. 감사.
켄 스미스

메서드를 정적으로 만들 필요가 없으므로 Html / Url / Model 등을 전달할 필요도 없습니다
Sheepy

12
@Sheepy, 그것은 절반에 불과합니다. 당신은 당신이 그들을 비 정적 할 수 있습니다 올바른지,하지만 당신은 단지 얻을 System.Web.WebPages.Html.HtmlHelper보다는 System.Web.Mvc.HtmlHelper. WebPages대부분의 확장 메서드가 .NET Framework에 대해 작성되기 때문에 버전이 적합하지 않을 가능성이 높습니다 System.Web.Mvc.HtmlHelper. 또한 Url속성 이 없으며 버전 에서 사용할 수없는이 UrlHelper필요합니다 . 결국 당신은 아마도 . RequestContextWebPagesMvc HtmlHelper
Kirk Woll 2012

1
도우미는 App_Code 폴더의 일부 여야합니다. ??
Vishal Sharma

1
예,이 파일은 {MyMvcProject}\App_Code`. It doesn't work as advertised when you place it elsewhere. The error *Cannot access non-static method 'TheThingToDo' in static context* disappears when you move MyHelper.cshtml`에 있어야합니다 App_Code. 뷰에서 DoSomething호출 할 수 있도록 정적이어야합니다 @MyHelper.DoSomething(..). 비 정적으로 만들면 MyHelperfirst 의 인스턴스를 만들어야합니다 .
Grilse

3

모든 경우에 TModel동일 할 것이고 (뷰에 대해 선언 된 모델), 제 경우 TValue에는 동일 할 것이므로 Expression 인수 유형을 선언 할 수있었습니다.

@helper FormRow(Expression<Func<MyViewModel, MyClass>> expression) {
  <div class="form-group">
    @(Html.LabelFor(expression, new { @class = "control-label col-sm-6 text-right" }))
    <div class="col-sm-6">
      @Html.EnumDropDownListFor(expression, new { @class = "form-control" })
    </div>
    @Html.ValidationMessageFor(expression)
  </div>
}

모델 필드는 모든 경우 string에, 당신은 대체 할 수 있습니다 MyClassstring.

정의 된 두 개 또는 세 개의 도우미를 정의하는 것이 나쁘지 않을 수도 TValue있지만, 추악한 코드를 생성 할 수있는 더 많은 것이 있다면 실제로 좋은 솔루션을 찾지 못했습니다. 나는 블록 @helper안에 넣은 함수에서 래핑을 시도했지만 @functions {}그 경로에서 작동하지 못했습니다.


당신이 그것에 대해 생각할 때 분명합니다. 만약 TModel당신이 아마 미리 알고있을 것입니다.
ta.speot.is

0

주요 문제는 얻을 경우 이름 람다 표현식을 사용하여 바인딩 속성 값을 것 같아 @Html.TextBoxFor(x => x.MyPoperty), 그리고 구성 요소는 매우 복잡한 HTML 태그를 가진 면도칼 도우미에서 구현해야하는지, 왜 단지의 확장 방법을 생성하지 않는 HtmlHelper<TModel>를 해결하는을 바인딩 이름 :

namespace System.Web.Mvc
{
    public static class MyHelpers
    {
        public static string GetNameForBinding<TModel, TProperty>
           (this HtmlHelper<TModel> model, 
            Expression<Func<TModel, TProperty>> property)
        {
            return ExpressionHelper.GetExpressionText(property);
        }
    }
}

면도기 도우미는 평소와 같아야합니다.

@helper MyComponent(string name)
{
    <input name="@name" type="text"/>
}

여기에서 사용할 수 있습니다

@TheHelper.MyComponent(Html.GetNameForBinding(x => x.MyProperty))

@ Html.IdFor (...)의 목적이 아닌가요?
Alex Dresko 2013

예, 할 수 @Htm.IdFor있지만 .ToHtmlString()도우미가 문자열을 필요로하는 문자열 ( ) 로 변환하려면 추가 프로세스가 필요합니다
ktutnik
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.