Html Helper для получения значений из модели состояния - PullRequest
3 голосов
/ 12 октября 2011

Asp.Net MVC 3

Кажется, у меня есть похожая проблема, поскольку на этот пост ответил Darin Dimitrov.Итак, Дарин, если вы читаете это, пожалуйста, помогите:)

asp.net-mvc2 - Сильно типизированные помощники, не использующие модель?

У меня проблема в том, что яищу помощника HTML, который будет содержать опубликованное значение в состоянии модели.

Например, если я использую редактор для этого:

@Html.EditorFor(model => model.SelectedTags)

Я могу видеть значение, которое было отправлено.Проблема в том, что мне нужен способ получить это значение без создания текстового поля, я просто хочу строку, потому что она мне нужна в каком-то javascript.

Я пробовал DisplayFor, но в нем нет опубликованного значения:

@Html.DisplayFor(model => model.SelectedTags)

Кстати, я не считаю это поведение интуитивно понятным вообще.Я потратил несколько часов на отладку ModelStateToTempDataAttribute из MVCContrib, думая, что это ошибка в их коде при импорте / экспорте состояния модели.

Спасибо за любую помощь!

Редактировать - Добавлен код Repro

Выполните следующие действия для воспроизведения:

  1. Запустите проект.Property1 должен быть пустым (обязательным), Property2 должен иметь «abc»
  2. Изменить Property2 на «xxx»
  3. Отправить форму (уведомление ClientValidationEnabled равно False)
  4. Форма опубликована,перенаправление, загрузка (PRG).Текстовое поле Property2 имеет «xxx», а справа внизу вы увидите «abc» из DisplayFor.

Контроллер

[ModelStateToTempData] //From MVCContrib
public class HomeController : Controller
{

    [HttpGet]
    public ActionResult Index()
    {
        //simulate load from db
        var model = new FormModel() { MyProperty2 = "abc" }; 

        return View(model);
    }

    [HttpGet]
    public ActionResult Success()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(FormModel model)
    {
        if (ModelState.IsValid)
        {
            return RedirectToAction("Success");
        }
        else
        {
            return RedirectToAction("Index");
        }
    }
}

Модель

public class FormModel
{
  [Required]
  public string MyProperty1 { get; set; }

  public string MyProperty2 { get; set; }
}

Вид

@model MvcApplication4.Models.FormModel
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
    <legend>FormModel</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.MyProperty1)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.MyProperty1)
        @Html.ValidationMessageFor(model => model.MyProperty1)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.MyProperty2)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.MyProperty2)
        @Html.ValidationMessageFor(model => model.MyProperty2)
    </div>

    @Html.DisplayFor(model => model.MyProperty2)

    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset>
}

Конфиг:

<add key="ClientValidationEnabled" value="false" />

ModelStateToTempData (MVCContrib):

public class ModelStateToTempDataAttribute : ActionFilterAttribute
    {
        public const string TempDataKey = "__MvcContrib_ValidationFailures__";

        /// <summary>
        /// When a RedirectToRouteResult is returned from an action, anything in the ViewData.ModelState dictionary will be copied into TempData.
        /// When a ViewResultBase is returned from an action, any ModelState entries that were previously copied to TempData will be copied back to the ModelState dictionary.
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            var modelState = filterContext.Controller.ViewData.ModelState;

            var controller = filterContext.Controller;

            if(filterContext.Result is ViewResultBase)
            {
                //If there are failures in tempdata, copy them to the modelstate
                CopyTempDataToModelState(controller.ViewData.ModelState, controller.TempData);
                return;
            }

            //If we're redirecting and there are errors, put them in tempdata instead (so they can later be copied back to modelstate)
            if((filterContext.Result is RedirectToRouteResult || filterContext.Result is RedirectResult) && !modelState.IsValid)
            {
                CopyModelStateToTempData(controller.ViewData.ModelState, controller.TempData);
            }
        }

        private void CopyTempDataToModelState(ModelStateDictionary modelState, TempDataDictionary tempData)
        {
            if(!tempData.ContainsKey(TempDataKey)) return;

            var fromTempData = tempData[TempDataKey] as ModelStateDictionary;
            if(fromTempData == null) return;

            foreach(var pair in fromTempData)
            {
                if (modelState.ContainsKey(pair.Key))
                {
                    modelState[pair.Key].Value = pair.Value.Value;

                    foreach(var error in pair.Value.Errors)
                    {
                        modelState[pair.Key].Errors.Add(error);
                    }
                }
                else
                {
                    modelState.Add(pair.Key, pair.Value);
                }
            }
        }

        private static void CopyModelStateToTempData(ModelStateDictionary modelState, TempDataDictionary tempData)
        {
            tempData[TempDataKey] = modelState;
        }
    }

Ответы [ 2 ]

3 голосов
/ 12 октября 2011

Вы можете прочитать эти значения из словаря состояния модели, например

<%:Html.ViewData.ModelState["key"] %>

Однако мне кажется, что SelectedTags - это перечисление объектов, которое отображается для редактирования при вызове EditorFor(model=>model.SelectedTags).в этом случае очень маловероятно, что вы что-то получите, позвонив по номеру Html.ViewData.ModelState["SelectedTags"].вместо этого вам придется перебирать ключи в словаре ModelState и проверять, начинается ли ключ с префикса SelectedTags, и тогда вы можете прочитать его значение соответствующим образом.

1 голос
/ 12 октября 2011

Создайте SelectedTags.cshtml

В ваших представлениях -> Общий доступ -> Шаблоны отображения. Это будет ваш шаблон отображения.Внутри напишите что-нибудь в строках

@model YourProject.WebUI.Models.SelectedTags

@for(int i = 0; i < Model.Tags.Count(); i++){
   // Assuming that selected tags contains a list of tags.
   // Replace <p> with whatever feels suitable
   <p>Model.Tags[i]</p>
}

. Затем вы можете использовать этот шаблон отображения в своих представлениях:

@Html.DisplayFor(model => model.SelectedTags,"SelectedTags") 

Это также должно работать:

@Html.DisplayFor(model => model.SelectedTags) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...