Модальное редактирование в MVC

Я искал способ обновить данные с помощью модального всплывающего окна. Сейчас я использую devexpress, потому что мы уже используем другие элементы управления devexpress (но это может измениться, если jquery библиотека была бы проще!!)

Я застрял с аспектом проверки. Честно говоря, весь процесс кажется довольно сложным для того, чего я пытаюсь достичь.

В любом случае, позвольте мне описать процесс, который я сейчас разработал:

Страница индекса содержит обзор различных элементов, которые можно обновить. Используя HtmlExtension, я смог создать всплывающее окно devexpress, которое загружает страницу редактирования при открытии всплывающего окна. => @Html.PopupControl().WithText("Редактировать").PopupGoesTo(Url.Action("EditPopup" и т.д.)

- Страница редактирования, которая является лишь частичным представлением, работает просто отлично. Я создал небольшую тестовую страницу, содержащую 1 текстовое поле, которое принимает десятичные дроби.

Я хочу отправить форму с помощью ajax (потому что, честно говоря, я понятия не имею, как я могу показать проверку, если я сделаю полный пост, так как мне нужно иметь возможность создать всплывающее окно и привязать к нему данные И запустить проверку ошибки).

  <script type="text/javascript">
    function EndPopUpUpdate(message) {
        if (message.url) {
            window.locatin.href = url;
        }
        $("#submitButtonPopUp, #loadingPopUp").toggle();
    }

    function BeginPopUpUpdate() {
        $("#submitButtonPopUp, #loadingPopUp").toggle();
    }
</script>

using (Ajax.BeginForm("Edit", "xxx", new AjaxOptions {  UpdateTargetId = "PopUpDiv", HttpMethod = "Post", OnBegin = "BeginPopUpUpdate", OnComplete = "EndPopUpUpdate"}, new { id = "PopUpForm" }))
    {
        <div id="PopUpDiv">
            @Html.Partial("EditPopup", new xxxViewModel())
        </div>
    }

Мне удалось добиться проверки, когда я выполняю обратную передачу, вручную перехватывая события jquery (потому что они не перехватываются, поскольку страница загружается динамически)

function ReconnectValidation() {
    $("#PopUpForm").ready(function () {
        $.validator.unobtrusive.parse("#PopUpForm");
    });

    $("#submitButton").click(function (e) {
        var form = $("#PopUpForm");
        if (!form.valid()) {
            e.preventDefault();
        }
    });
}

Так что это обрабатывает мою проверку на стороне клиента, которая работает.

Теперь, моя актуальная проблема! Проверка на стороне сервера.

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([ModelBinder(typeof(CommandModelBinder))] UpdateCommand command)
    {
        if (!ModelState.IsValid)
        {
            //using the command pattern
            var handlerResult = HandlerLocator.GetQueryHandler<IGetOverviewHandler>().Execute(..);
            return PartialView("EditPopUp", handlerResult.ViewModel);
        }

        HandlerLocator.GetCommandHandler<UpdateCommand>().Handle(command);
        var returnLink = Url.Action("Index", new {..});
        return Json(new { url = returnLink }, JsonRequestBehavior.AllowGet);
    }

Я написал CustomModelBinder, который ничего не делает, кроме как ищет свойства в моем объекте команды (моя возвращаемая модель, если хотите) и ищет в коллекции форм, может ли он найти соответствующий объект с тем же именем. Затем он пытается преобразовать его и привязывает ModelError к моему ModelState, если это не удается.

Итак, теперь у нас есть ModelState, который либо действителен, либо недействителен. Если это действительно так, я хочу перенаправить на индекс (чтобы мой обзор мог обновляться). Я читал, что должен обрабатывать это на стороне клиента, потому что ajax.BeginForm собирается заменить "PopUpDiv" -div результатом (который просто создает ту же страницу на моей странице).

Вот событие onComplete:

function EndPopUpUpdate(message) {
            if (message.url) {
                window.locatin.href = url;
            }
            $("#submitButtonPopUp, #loadingPopUp").toggle();
        }

Проблема в том, что я не получаю сообщение json, но получаю PartialView. Это означает, что я не могу получить доступ к message.url..потому что это не то, что я получаю :/

Итак, проблема номер 1

Если объект недействителен, я хочу вернуть частичное представление с моделью и выдать пользователю ошибку. Когда я возвращаю частичное представление, оно просто заменяет текущее представление, но не показывает никаких ошибок проверки..

Это проблема №2 :)

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

Извините за длинное сообщение, но надеюсь все понятно.

Спасибо за вашу помощь и время!


person Team-JoKi    schedule 05.06.2012    source источник
comment
Почему бы вам не связаться с ребятами из DX по поводу вашей проблемы?   -  person Mikhail    schedule 05.06.2012
comment
Взгляните на этот учебник, чтобы упростить процесс. Он старый, но легко адаптируется к mvc3. Этот метод охватывает модальные окна со строго типизированными представлениями, а также проверку на стороне клиента и сервера. weirdlover.com/2010/05/14/   -  person seraphym    schedule 09.06.2012


Ответы (1)


Раньше я использовал плагин диалога из jQuery UI (), который, как я обнаружил, работает хорошо. Обычно я открываю ссылки в iframe во всплывающем окне, что позволяет избежать описанной вами проблемы, когда события проверки jQuery не подключаются, потому что страница загружается динамически - проверка как на стороне клиента, так и на стороне сервера должна работать как обычно , только в этом iframe.

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

@Html.ActionLink("Edit", "Edit", new { id = Model.Id }, new { @class = "popup" })

Затем вы можете открыть эти ссылки в диалоговом окне iframe с помощью jQuery, например:

$("a.popup").click(function(e) {
    e.preventDefault();
    $("<iframe />").attr("src", $(this).attr("href") + "?popup=true").dialog({ show: "fadeIn", modal: true, width: 300, height: 300});
});

Это в основном ищет всплывающие ссылки, отменяет поведение по умолчанию (навигация по страницам) и открывает этот URL-адрес в iframe во всплывающем окне, добавляя строку запроса, чтобы определить, что страница находится во всплывающем окне. Причина этой строки запроса и знание того, что это всплывающее окно, позволяет вам загружать другую страницу макета в представлении, возможно, через фильтр действий, например:

public class Popup : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result != null
            && filterContext.Result is ViewResult
            && filterContext.RequestContext.HttpContext.Request["popup"] == "true")
            (filterContext.Result as ViewResult).MasterName = "~/Views/Shared/_PopupLayout.cshtml";
    }
}

Это означает, что вы можете легко применить этот атрибут к классам, где вы хотите применять методы действия. Этот метод также означает, что если вы передумаете о реализации в будущем (например, удалите всплывающие окна), вы можете легко удалить jQuery, который отменяет клики, и ваше приложение продолжит функционировать как обычное приложение MVC с отдельными страницами и всеми навигация/проверка и т. д. будут «просто работать».

Я надеюсь, что все имеет смысл и помогает.

person Ian Routledge    schedule 06.08.2012