Как правильно разместить на 2 одинаковых формах по отдельности из одного представления? - PullRequest
4 голосов
/ 23 ноября 2011

Похоже, это довольно распространенный вопрос, который я видел здесь на stackoverflow, но, похоже, никто не нашел ответ, который я ищу. У меня есть 2 формы (стандартный логин пользователя и форма регистрации), которые я хотел бы видеть в одном окне. Он работает правильно, если все идет хорошо, но если у них сбой и форма повторного сообщения 2 происходят нежелательные вещи:

  1. Обе формы пытаются проверить, хотя была заполнена только одна.
  2. Идентификатор для ввода 'username' одинаков в обеих формах, поэтому данные, введенные в одну, заполняются в обеих.

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

Вот код:

@{
ViewBag.Title = "Log On";
}
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript">      </script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@{Html.RenderPartial("LogIn",  (FortyEightHourPrint.Models.LogOnModel)ViewBag.LogInModel);}
@{Html.RenderPartial("Register", (FortyEightHourPrint.Models.RegisterModel)ViewBag.RegisterModel);}

и регистр частичного просмотра

@using (Html.BeginForm("Register","Account")) {
@Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.")
<div>
    <fieldset>
        <legend>Account Information</legend>

        <div class="editor-label">
            @Html.LabelFor((m => m.UserName))
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(m => m.UserName)
            @Html.ValidationMessageFor(m => m.UserName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(m => m.Email)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(m => m.Email)
            @Html.ValidationMessageFor(m => m.Email)
        </div>

        <div class="editor-label">
            @Html.LabelFor(m => m.Password)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(m => m.Password)
            @Html.ValidationMessageFor(m => m.Password)
        </div>

        <div class="editor-label">
            @Html.LabelFor(m => m.ConfirmPassword)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(m => m.ConfirmPassword)
            @Html.ValidationMessageFor(m => m.ConfirmPassword)
        </div>

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

и логин

    @using (Html.BeginForm("LogIn","Account"))
{
<div>
    <fieldset>
        <legend>Account Information</legend>

        <div class="editor-label">
            @Html.LabelFor(m => m.UserName)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(m => m.UserName)
            @Html.ValidationMessageFor(m => m.UserName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(m => m.Password)
        </div>
        <div class="editor-field">
            @Html.PasswordFor(m => m.Password)
            @Html.ValidationMessageFor(m => m.Password)
        </div>

        <div class="editor-label">
            @Html.CheckBoxFor(m => m.RememberMe)
            @Html.LabelFor(m => m.RememberMe)
        </div>

        <p>
            <input type="submit" value="Log On" />
        </p>
    </fieldset>
</div>
}

и, конечно, то, что делает контроллер

   public ActionResult LogOn()
    {
        if ((bool)(ViewBag.OkToRedirect ?? false))
            return Redirect(getReturnUrl(ViewBag.ReturnUrl));
        return View();
    }
   public PartialViewResult LogIn()
    {
        return PartialView();
    }
    //
    // POST: /Account/LogIn

    [HttpPost]
    public ViewResult LogIn(LogOnModel model, string returnUrl)
    {
        ViewBag.OkToRedirect = false;
        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                ViewBag.OkToRedirect = true;
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }
        ViewBag.LogInModel = model;
        ViewBag.ReturnUrl = returnUrl;
        return View("LogOn");
    }


    public PartialViewResult Register()
    {
        return PartialView();
    }

    //
    // POST: /Account/Register

    [HttpPost]
    public ViewResult Register(RegisterModel model, string returnUrl)
    {
        ViewBag.OkToRedirect = false;
        if (ModelState.IsValid)
        {
            // Attempt to register the user
            MembershipCreateStatus createStatus;
            Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);

            if (createStatus == MembershipCreateStatus.Success)
            {
                FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
                ViewBag.OkToRedirect = true;
            }
            else
            {
                ModelState.AddModelError("", ErrorCodeToString(createStatus));
            }
        }

        ViewBag.RegisterModel = model;
        ViewBag.ReturnUrl = returnUrl;
        return View("LogOn");
    }

Кроме того, я новичок в mvc, так что если кто-нибудь может предложить лучший подход, я весь слух.

Ответы [ 2 ]

3 голосов
/ 23 ноября 2011
  1. Добавьте эти методы расширения в некоторый класс:

    public static IDisposable BeginFieldPrefix<TModel>(this HtmlHelper<TModel> html,
        Expression<Func<TModel, object>> expression)
    {
        return BeginFieldPrefix(html, (LambdaExpression) expression);
    }
    
    internal static IDisposable BeginFieldPrefix(this HtmlHelper html, LambdaExpression expression)
    {
        return BeginFieldPrefix(html, html.GetName(ExpressionHelper.GetExpressionText(expression)));
    }
    
    public static IDisposable BeginFieldPrefix(this HtmlHelper html, string fieldPrefix)
    {
        var templateInfo = html.ViewData.TemplateInfo;
        string oldFieldPrefix = templateInfo.HtmlFieldPrefix;
        templateInfo.HtmlFieldPrefix = fieldPrefix;
        return Disposable.Create(() => templateInfo.HtmlFieldPrefix = oldFieldPrefix);
    }
    
    public static string GetName<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        return html.GetName(ExpressionHelper.GetExpressionText(expression));
    }
    
    public static string GetName(this HtmlHelper html, string expression)
    {
        return html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expression);
    }
    

Disposable класс расположен в Rx Framework: http://msdn.microsoft.com/en-us/library/system.reactive.disposables.disposable(v=vs.103).aspx

  1. Используйте следующий код в вашем блоке BeginForm для префикса всех полей:

    @ using (Html.BeginFieldPrefix ("LoginForm")) {...}

    @ using (Html.BeginFieldPrefix ("RegisterForm")) {...}

  2. Использование перегрузки UpdateModel и TryUpdateModel, позволяющей указывать префикс поля вместо неявного обновления модели (см http://msdn.microsoft.com/en-us/library/dd493137.aspx).

0 голосов
/ 23 ноября 2011

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

Этот пост очень помог мне.

Надеюсь, это поможет,

Мэтт

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