zoukankan      html  css  js  c++  java
  • 使用Html.BeginForm<T>后客户端脚本验证出错的问题

    使用Html.BeginForm<T>方法生成form后,客户端脚本验证一直出错,调试发现FormID一直是null,而使得脚本运行报错,而使用Html.BeginForm()方法则没有这个问题。仔细研究后发现此确系mvc框架的bug。
    我们不得不重写一个扩展类来扩展HtmlHelper方法而修正这个bug。查阅外国资料时有人写了一部分代码但仍有bug,先修正如下见红色代码部分。
    namespace System.Web.Mvc
    {
        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Diagnostics.CodeAnalysis;
        using System.Globalization;
        using System.Linq.Expressions;
        using System.Web.Mvc.Html;
        using System.Web.Routing;
        using TSharp.Core.Util;
    
        public static class FormExtensions
        {
            [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an Extension Method which allows the user to provide a strongly-typed argument via Expression")]
            public static MvcForm BeginFormA<TController>(this HtmlHelper helper, Expression<Action<TController>> action) where TController : Controller
            {
                return BeginFormA<TController>(helper, action, FormMethod.Post, null);
            }
    
            [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an Extension Method which allows the user to provide a strongly-typed argument via Expression")]
            public static MvcForm BeginFormA<TController>(this HtmlHelper helper, Expression<Action<TController>> action, FormMethod method) where TController : Controller
            {
                return BeginFormA<TController>(helper, action, method, null);
            }
    
            [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an Extension Method which allows the user to provide a strongly-typed argument via Expression")]
            public static MvcForm BeginFormA<TController>(this HtmlHelper helper, Expression<Action<TController>> action, FormMethod method, object htmlAttributes) where TController : Controller
            {
                return BeginFormA<TController>(helper, action, method, new RouteValueDictionary(htmlAttributes));
            }
    
    
            private static readonly object _lastFormNumKey = new object();
    
            private static int IncrementFormCount(IDictionary items)
            {
                object lastFormNum = items[_lastFormNumKey];
                int newFormNum = (lastFormNum != null) ? ((int)lastFormNum) + 1 : 0;
                items[_lastFormNumKey] = newFormNum;
                return newFormNum;
            }
    
            [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an Extension Method which allows the user to provide a strongly-typed argument via Expression")]
            public static MvcForm BeginFormA<TController>(this HtmlHelper helper, Expression<Action<TController>> action, FormMethod method, IDictionary<string, object> htmlAttributes) where TController : Controller
            {
                TagBuilder tagBuilder = new TagBuilder("form");
                if (helper.ViewContext.ClientValidationEnabled)
                {
                    // forms must have an ID for client validation
                    // 是必须有个id,可是不能仅使用自动生成 by tangjingbo @2010-10-28
                    var formId = SafeConvert.ToString(htmlAttributes["id"]);
                    if (string.IsNullOrEmpty(formId))
                    {
                        int formNum = IncrementFormCount(helper.ViewContext.HttpContext.Items);
                        formId = String.Format(CultureInfo.InvariantCulture, "form{0}", formNum);
                    }
                    tagBuilder.GenerateId(formId);
                }
                tagBuilder.MergeAttributes(htmlAttributes);
                string formAction = Microsoft.Web.Mvc.LinkExtensions.BuildUrlFromExpression(helper, action);
                tagBuilder.MergeAttribute("action", formAction);
                tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method));
    
                helper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
                var theForm = new MvcForm(helper.ViewContext);
    
                if (helper.ViewContext.ClientValidationEnabled)
                {
                    helper.ViewContext.FormContext.FormId = tagBuilder.Attributes["id"];
                }
    
                return theForm;
            }
        }
    }
    
     
    英文资料:
     

    Html.BeginForm<T> does not the same things as Html.BeginForm()

    Description

    Hi!
    I'm using the Html.EnableClientValidation() method. When I use Html.BeginForm(...), it works fine. When I use Html.BeginForm<T>(...), it does not work.
    The generated javascript have this setting: "FormId":"null"
    I think it's because the generic does'nt set the FormContext.FormId property.

    File Attachments

    No files are attached

    Closed by

    Comments

    billrob458 wrote Sep 16 at 4:09 AM

    This ticket should be called.
    Html.BeginForm<T> does not work with mvc ajax client validation.

    sydneyos wrote Sep 8 at 11:49 PM

    If I try to add these lines, I get "ViewContext does not contain a definition for 'FormIdGenerator'" - seems to be an internal property.

    ondrejsv wrote Aug 24 at 10:18 PM

    The generic version does not make use of these lines included in the FormHelper extension method which the non-generic BeginForm uses:
    if (htmlHelper.ViewContext.ClientValidationEnabled) {
    // forms must have an ID for client validation
    tagBuilder.GenerateId(htmlHelper.ViewContext.FormIdGenerator());
    }
    The fix is easy, just include those lines. Meantime you can use your own extension method (copy the source from the MvcFutures project\Mvc\FormExtensions.cs) with the afore mentioned lines.

    maird wrote Jun 1 at 7:31 PM

    I'm running into a related, but different, issue with Html.BeginForm<T>. For some reason, it is picking up on a Route to an Area when it shouldn't. Html.BeginForm correctly renders the form action without the Area prefix.

    maird wrote Jun 1 at 7:31 PM

    I'm running into a related, but different, issue with Html.BeginForm<T>. For some reason, it is picking up on a Route to an Area when it shouldn't. Html.BeginForm correctly renders the form action without the Area prefix.

  • 相关阅读:
    自定义ASP.NET MVC Html标签辅助方法
    解决github.com无法访问
    Func<>用法
    Entity Framework 在OrderBy排序中使用字符串
    <input type="file"> 标签详解
    JS实现上传图片的三种方法并实现预览图片功能
    一个关于双目运算符的测试
    堆和栈的区别
    C# 代码笔记_tuple元组
    小程序前后端自定义登录与一键登录兼容demo分享
  • 原文地址:https://www.cnblogs.com/68681395/p/1863671.html
Copyright © 2011-2022 走看看