Можно ли создать общий метод @helper с помощью Razor? - PullRequest
85 голосов
/ 21 января 2011

Я пытаюсь написать помощник в Razor, который выглядит следующим образом:

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

К сожалению, парсер считает, что <T - это начало элемента HTML, и я получаю синтаксическую ошибку. Можно ли создать помощника с Razor, который является универсальным методом? Если да, то каков синтаксис?

Ответы [ 4 ]

122 голосов
/ 13 марта 2011

Это возможно , которое можно получить внутри вспомогательного файла с синтаксисом @functions, но если вам нужна читаемость в стиле бритвы, на которую вы ссылаетесь, вам также потребуется вызвать обычного помощника для выполнения HTML подгонка и отделка.

Обратите внимание, что функции в файле Helper являются статическими, поэтому вам все равно придется передавать экземпляр HtmlHelper со страницы, если вы намеревались использовать его методы.

например. Просмотров \ 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>
}
...
50 голосов
/ 21 января 2011

Нет, это невозможно. Вместо этого вы можете написать обычный помощник 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 T : class
{
    ...
}

, что позволит вам вызывать его следующим образом (при условии, конечно, что ваше представление строго типизировано, но это безопасное предположение, поскольку все представления должны быть строго типизированы в любом случае: -)):

@Html.DoSomething(x => x.SomeProperty)
3 голосов
/ 26 февраля 2015

Во всех случаях 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, вы можете заменить MyClass на string.

Возможно, было бы неплохо определить двух или трех помощников с помощьюTValue определено, но если у вас есть еще что-нибудь, что сгенерирует некрасивый код, я действительно не нашел хорошего решения.Я попытался обернуть @helper из функции, которую я поместил внутри блока @functions {}, но мне так и не удалось заставить его работать по этому пути.

0 голосов
/ 15 ноября 2013

, если ваша основная проблема заключается в том, чтобы получить значение атрибута name для привязки с использованием лямбда-выражения, похоже на @Html.TextBoxFor(x => x.MyPoperty), и если ваш компонент имеет очень сложные теги html и должен быть реализован на Razor Helper, то почемуне просто создайте метод расширения 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...