MVC3 RemoteAttribute и несколько кнопок отправки - PullRequest
3 голосов
/ 30 мая 2011

Я обнаружил ошибку, возникающую при использовании MVC 3 с RemoteAttibute и ActionNameSelectorAttribute.

Я реализовал решение для поддержки нескольких кнопок отправки в одном представлении, аналогичном этому сообщению: http://blog.ashmind.com/2010/03/15/multiple-submit-buttons-with-asp-net-mvc-final-solution/

Решение работает, однако, когда я представляю RemoteAttribute в моей модели, controllerContext.RequestContext.HttpContext.Request больше не содержит ни одной из моих кнопок отправки, что приводит к сбою решения «multi-submit-button».

Кто-нибудь еще испытывал этот сценарий?

Ответы [ 4 ]

1 голос
/ 30 мая 2011

Я знаю, что это не прямой ответ на ваш вопрос, но я бы предложил альтернативное решение для нескольких кнопок отправки, используя вместо этого JQuery и разметку на стороне клиента:

Javascript

<script type="text/javascript">
    $(document).ready(function () {
        $("input[type=submit][data-action]").click(function (e) {
            var $this = $(this);
            var form = $this.parents("form");
            var action = $this.attr('data-action');
            var controller = $this.attr('data-controller');
            form.attr('action', "/" + controller + "/" + action);
            form.submit();
            e.preventDefault();
        });
    });
</script>

Html

@using (Html.BeginForm())
{    
    <input type="text" name="name" id="name" />

    <input type="submit" value="Save draft" data-action="SaveDraft" data-controller="Home" />
    <input type="submit" value="Publish" data-action="Publish" data-controller="Home" />
}

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

По сути, это происходит потому, что при нажатии кнопки submit с набором атрибутов data-action родительские формы заменяют атрибут действия родительской формы комбинацией атрибутов data-controller и data-action на нажатой кнопке, и затем запускает submit-событие формы.

Конечно, этот конкретный пример плохо универсален и всегда будет создавать / Controller / Action url, но его можно легко расширить, добавив немного логики в действие click.

Просто совет:)

0 голосов
/ 18 июля 2013

Я столкнулся с той же проблемой.

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

В результате я получил форму Ajax, удалив атрибут Remote и проверив поле с помощью ModelState.

0 голосов
/ 01 июня 2011

Проблема проявляется, когда RemoteAttribute используется на модели в представлении, где используются кнопки отправки нескольких элементов.Независимо от того, какое «многокнопочное» решение вы используете, POST больше не содержит входных данных для отправки.

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

ViewModel

public class NomineeViewModel
    {
        [Remote("UserAlreadyRegistered", "Nominee", AdditionalFields="Version", ErrorMessage="This Username is already registered with the agency.")]
        public string UserName { get; set; }

        public int Version {get; set;}
        public string SubmitButtonName{ get; set; }
    }

ActionMethodSelectorAttribute

public class OnlyIfPostedFromButtonAttribute : ActionMethodSelectorAttribute
    {
        public String SubmitButton { get; set; }
        public String ViewModelSubmitButton { get; set; }

        public override Boolean IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
        {
            var buttonName = controllerContext.HttpContext.Request[SubmitButton];
            if (buttonName == null)
            {
                //This is neccessary to support the RemoteAttribute that appears to intercepted the form post
                //and removes the submit button from the Request (normally detected in the code above)
                var viewModelSubmitButton = controllerContext.HttpContext.Request[ViewModelSubmitButton];
                if ((viewModelSubmitButton == null) || (viewModelSubmitButton != SubmitButton))
                    return false;
            }

            // Modify the requested action to the name of the method the attribute is attached to
            controllerContext.RouteData.Values["action"] = methodInfo.Name;
            return true;
        }
    }

Просмотр

<script type="text/javascript" language="javascript">
    $(function () {
        $("input[type=submit][data-action]").click(function (e) {
            var action = $(this).attr('data-action');
            $("#SubmitButtonName").val(action);
        });
    });
</script>

    <% using (Html.BeginForm())
       {%>
        <p>
            <%= Html.LabelFor(m => m.UserName)%>
            <%= Html.DisplayFor(m => m.UserName)%>
        </p>

        <input type="submit" name="editNominee" value="Edit" data-action="editNominee" />
        <input type="submit" name="sendActivationEmail" value="SendActivationEmail" data-action="sendActivationEmail" />
        <%=Html.HiddenFor(m=>m.SubmitButtonName) %>
<% } %>

Контроллер

[AcceptVerbs(HttpVerbs.Post)]
[ActionName("Details")]
[OnlyIfPostedFromButton(SubmitButton = "editNominee", ViewModelSubmitButton = "SubmitButtonName")]
public ActionResult DetailsEditNominee(NomineeViewModel nom)
{
    return RedirectToAction("Edit", "Nominee", new { id = nom.UserName });
}

[AcceptVerbs(HttpVerbs.Post)]
[ActionName("Details")]
[OnlyIfPostedFromButton(SubmitButton = "sendActivationEmail", ViewModelSubmitButton = "SubmitButtonName")]
public ActionResult DetailsSendActivationEmail(NomineeViewModel nom)
{
    return RedirectToAction("SendActivationEmail", "Nominee", new { id = nom.UserName });
}

[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public ActionResult UserAlreadyRegistered(string UserName, int Version)
{
    //Only validate this property for new records (i.e. Version != zero)
    return Version != 0 ? Json(true, JsonRequestBehavior.AllowGet) 
                              : Json(! nomineeService.UserNameAlreadyRegistered(CurrentLogonDetails.TaxAgentId, UserName), JsonRequestBehavior.AllowGet);
}
0 голосов
/ 30 мая 2011

Я не уверен, что это ошибка в MVC 3, поскольку это не то, что вы ожидали.RemoteAttribute заставляет javascript перехватывать и проверять форму с помощью сообщения ajax.для этого публикация формы, вероятно, отменяется, и когда проверка завершена, событие отправки формы, вероятно, вызывается напрямую, а не с использованием фактически нажатой кнопки.Я вижу, где это может быть проблематично в вашем сценарии, но это имеет смысл.мое предложение, либо не используйте RemoteAttribute и не проверяйте вещи самостоятельно, либо не выполняйте несколько действий с формой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...