Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/451.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何避免在ASP.NET代码中编写凌乱的JavaScript?_C#_Javascript_Asp.net_Webforms_Code Behind - Fatal编程技术网

C# 如何避免在ASP.NET代码中编写凌乱的JavaScript?

C# 如何避免在ASP.NET代码中编写凌乱的JavaScript?,c#,javascript,asp.net,webforms,code-behind,C#,Javascript,Asp.net,Webforms,Code Behind,我在问,在ASP.NET中使用Javascript的最佳实践是什么 我不知道这是否是最佳实践,但我在codebehind中添加了javascript客户端事件。它工作正常,但这是最佳实践吗 例如,我得到了一个单选按钮控件,并在页面_Init中添加了Javascript客户端事件。页面初始化可以多次调用,因此每次调用页面时都会呈现Javascript 此外,调试长Javascript字符串也很困难。怎样才能更干净。。。有办法吗 让我们看一个包含Javascript的变量示例: scripts.Te

我在问,在ASP.NET中使用Javascript的最佳实践是什么

我不知道这是否是最佳实践,但我在codebehind中添加了javascript客户端事件。它工作正常,但这是最佳实践吗

例如,我得到了一个单选按钮控件,并在页面_Init中添加了Javascript客户端事件。页面初始化可以多次调用,因此每次调用页面时都会呈现Javascript

此外,调试长Javascript字符串也很困难。怎样才能更干净。。。有办法吗

让我们看一个包含Javascript的变量示例:

scripts.Text += "<script type='text/javascript'>function ValidateDdl" + metachamp.ID +
"(sender, args) {  if(" + txtReason.ClientID + ".GetText() != '' ||" +
dynamicControl.ClientID +
".style.display == 'none' || HiddenFieldSaveError.Contains('" + metachamp.ID +
"') ){" + dynamicControl.ClientID + ".className='';HiddenFieldError.Remove(" +
metachamp.ID + ");" + errorImage.ClientID +
".SetClientVisible(false);args.IsValid = true;}else{var comboVal = document.getElementById('" +
Image9.ClientID + "'.substring(0,'" + Image9.ClientID +
"'.length - 6) + 'ddl').value ;if (comboVal != '0' ) {args.IsValid = true;HiddenFieldError.Remove(" +
metachamp.ID + ");" + validImage.ClientID +
".SetClientVisible(false);HiddenField.Remove('Bypass-' + '" +
metachamp.ID.ToString() + "');HiddenFieldSaveError.Remove(" + metachamp.ID +
");" + dynamicControl.ClientID + ".className='';" + errorImage.ClientID +
".SetClientVisible(false);}";
scripts.Text+=“function ValidateDdl”+metachamp.ID+
“(发送方,args){if(“+txtReason.ClientID+”.GetText()!=”||”+
dynamicControl.ClientID+
.style.display==“无”| | HiddenFieldSaveError.Contains(“+metachamp.ID+
“){”+dynamicControl.ClientID+”.className='';HiddenFieldError.Remove(“+
metachamp.ID+”;“+errorImage.ClientID+
“.SetClientVisible(false);args.IsValid=true;}else{var comboVal=document.getElementById(””+
Image9.ClientID+“”。子字符串(0,“+Image9.ClientID+
“'.length-6)+'ddl').value;if(comboVal!=“0”){args.IsValid=true;HiddenFieldError.Remove(”+
metachamp.ID+”;“+validImage.ClientID+
.SetClientVisible(false);HiddenField.Remove('Bypass-'+')”+
metachamp.ID.ToString()+”);HiddenFieldSaveError.Remove(“+metachamp.ID+
”;“+dynamicControl.ClientID+”。类名=”;“+errorImage.ClientID+
“.SetClientVisible(false);}”;
第一步是将JavaScript从代码隐藏和值插值中分离出来。这种方法不是动态构建JavaScript,而是使用一个给定参数的JavaScript函数

在第一个阶段之后,我们最终得到了如下内容(请原谅部分翻译,它伤了我的头)。注意闭包生成器模式的使用;在实际代码中,我将进一步将其作为一个单独的模块

函数makeValidator(champId,opts){
返回函数(发送方,参数){
//现在是时候了,哈利。。
//
//在ASP.NET中使用$get(和$find),尤其是在
//处理ASP.NET AJAX集成以按ID查找控件。
//
//但是,代码使用的似乎是某些DevExpress
//控件,因此必须以不同的方式进行访问,主要是
//1.`window[clientId]`或
//2.`ASPxClientControl.GetControlCollection().GetByName(id)`
//这只是需要处理的令人讨厌的事情之一;我已经展示了它的用法
//它可能也需要应用于其他控件。
//
var reasonControl=window[opts.reasonId];//DX控件
var dynamicControl=$get(opts.dynamicControlId);//普通ASP.NET/DOM
var errorImage=window[opts.errorImageId];//DX控件
if(reasonControl.GetText()!=“dynamicControl.style.display=”无”){
dynamicControl.className='';
errorImage.SetClientVisible(false);
args.IsValid=true;
}
//等等。
}
}
应该清楚的是,JavaScript代码与任何字符串插值都是分开的。这是一个正常的函数,当使用某些参数(由API定义)调用时,具有特定的行为。虽然“加载/注入”此JavaScript有不同的方法(当UpdatePanel和嵌套/复杂层次结构发挥作用时,这一点很重要),让我们假设它当前位于页面标记中的

现在,让我们将验证器连接到控件-这完全是虚构的,但它显示了数据绑定的用法,并在后面的代码中实际创建了JavaScript“调用”,稍后我们将了解原因。(正确使用数据绑定实际上很重要,因为它会延迟调用CreateValidator函数,直到分配了控件的clientID。)


对于任何技术堆栈来说,这都是一个经典问题。要回答这个问题,我需要记住以下几点:

  • 不要重复你自己(使用WebForms可能会更困难)
  • 做一件事,把它做好
  • 我发现客户端功能分为两类:

    • 表单验证,通常是应该在后端代码中管理的业务规则的扩展
    • 可用性增强,如下拉菜单,当焦点从文本字段移开时自动大写文本,等等
    • 用户交互管理,这可能是由后端不容易完成的业务规则驱动的
    注意:下面的代码可能有一些bug,但它应该能告诉您主要的想法)

    使用ASP.NET WebForms进行表单验证 这是给我带来最大痛苦的领域。我目前正在尝试使用WebForms,实际上进展很顺利。关于验证,我最好的建议是:不要使用
    验证器!
    这就是人们抱怨WebForms是一个复制粘贴框架的原因。它不起作用我们必须这样做。在快速编写代码示例之前,也不要使用数据[Set | Table | Row]。您获得了所有数据,但没有任何行为。请使用类似ORM的实体框架或NHibernate,并让所有ASP页面处理实体类,因为这样您就可以使用FluentValidation:

    应用程序代码/模型/实体/Post.cs

    namespace Project.Models.Entities
    {
        public class Post
        {
            public int Id { get; set; }
            public string Title { get; set; }
            public string Body { get; set; }
            public DateTime CreatedAt { get; set; }
            public DateTime? ModifiedAt { get; set; }
        }
    }
    
    using FluentValidation;
    using Project.Models.Entities;
    
    namespace Project.Models.Validators
    {
    
        public class PostValidator : AbstractValidator<Post>
        {
            public PostValidator()
            {
                RuleFor(p => p.Title)
                    .NotEmpty()
                    .Length(1, 200);
    
                RuleFor(p => p.Body)
                    .NotEmpty();
            }
        }
    }
    
    namespace Project.UserControls
    {
        public class PostControl : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                if (Page.IsPostBack)
                {
                    PostValidator validator = new PostValidator();
                    Post entity = new Post()
                    {
                        // Map form fields to entity properties
                        Id = Convert.ToInt32(PostId.Value),
                        Title = PostTitle.Text.Trim(),
                        Body = PostBody.Text.Trim()
                    };
                    ValidationResult results = validator.Validate(entity);
    
                    if (results.IsValid)
                    {
                        // Save to the database and continue to the next page
                    }
                    else
                    {
                        BulletedList summary = (BulletedList)FindControl("ErrorSummary");
    
                        // Display errors to the user
                        foreach (var failure in results.Errors)
                        {
                            Label errorMessage = FindControl(failure.PropertyName + "Error") as Label;
    
                            if (errorMessage == null)
                            {
                                summary.Items.Add(new ListItem(failure.ErrorMessage));
                            }
                            else
                            {
                                errorMessage.Text = failure.ErrorMessage;
                            }
                        }
                    }
                }
                else
                {
                    // Display form
                }
            }
    
            ...
        }
    }
    
    function FooWidget(element) {
        this.$element = $(element);
        this.fillOptions = this.fillOptions.bind(this);
        this.$element.on("click", "[data-action=fillOptions]", this.fillOptions);
    }
    
    FooWidget.prototype = {
        constructor: FooWidget,
    
        fillOptions: function(event) {
            // make ajax request:
    
            var select = this.$element.find("select:first")[0],
                option = null;
    
            option = document.createElement("option");
            option.value = "...";
            option.text = "...";
            select.appendChild(option);
    
            ...
        },
    
        focus: function() {
            this.$element.find(":input:first").focus();
        }
    };
    
    应用程序代码/Models/validator/PostValidator.cs

    namespace Project.Models.Entities
    {
        public class Post
        {
            public int Id { get; set; }
            public string Title { get; set; }
            public string Body { get; set; }
            public DateTime CreatedAt { get; set; }
            public DateTime? ModifiedAt { get; set; }
        }
    }
    
    using FluentValidation;
    using Project.Models.Entities;
    
    namespace Project.Models.Validators
    {
    
        public class PostValidator : AbstractValidator<Post>
        {
            public PostValidator()
            {
                RuleFor(p => p.Title)
                    .NotEmpty()
                    .Length(1, 200);
    
                RuleFor(p => p.Body)
                    .NotEmpty();
            }
        }
    }
    
    namespace Project.UserControls
    {
        public class PostControl : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                if (Page.IsPostBack)
                {
                    PostValidator validator = new PostValidator();
                    Post entity = new Post()
                    {
                        // Map form fields to entity properties
                        Id = Convert.ToInt32(PostId.Value),
                        Title = PostTitle.Text.Trim(),
                        Body = PostBody.Text.Trim()
                    };
                    ValidationResult results = validator.Validate(entity);
    
                    if (results.IsValid)
                    {
                        // Save to the database and continue to the next page
                    }
                    else
                    {
                        BulletedList summary = (BulletedList)FindControl("ErrorSummary");
    
                        // Display errors to the user
                        foreach (var failure in results.Errors)
                        {
                            Label errorMessage = FindControl(failure.PropertyName + "Error") as Label;
    
                            if (errorMessage == null)
                            {
                                summary.Items.Add(new ListItem(failure.ErrorMessage));
                            }
                            else
                            {
                                errorMessage.Text = failure.ErrorMessage;
                            }
                        }
                    }
                }
                else
                {
                    // Display form
                }
            }
    
            ...
        }
    }
    
    function FooWidget(element) {
        this.$element = $(element);
        this.fillOptions = this.fillOptions.bind(this);
        this.$element.on("click", "[data-action=fillOptions]", this.fillOptions);
    }
    
    FooWidget.prototype = {
        constructor: FooWidget,
    
        fillOptions: function(event) {
            // make ajax request:
    
            var select = this.$element.find("select:first")[0],
                option = null;
    
            option = document.createElement("option");
            option.value = "...";
            option.text = "...";
            select.appendChild(option);
    
            ...
        },
    
        focus: function() {
            this.$element.find(":input:first").focus();
        }
    };
    
    UserControls/PostControl.ascx

    <asp:BulletedList ID="ErrorSummary" runat="server" CssClass="Error-Summary" />
    
    <p>
        <asp:Label ID="PostTitleLabel" AssociatedControlID="PostTitle" runat="server">* Title:</asp:Label>
        <asp:TextBox ID="PostTitle" runat="server" />
        <asp:Label ID="PostTitleError" runat="server" CssClass="Error" />
    </p>
    
    <p>
        <asp:Label ID="PostBodyLabel" AssociatedControlID="PostBody" runat="server">* Body:</asp:Label>
        <asp:TextBox ID="PostBody" runat="server" TextMode="MultiLine" />
        <asp:Label ID="PostBodyError" runat="server" CssClass="Error" />
    </p>
    
    <asp:HiddenField ID="PostId" runat="server" />
    
    <dx:ASPxRadioButtonList runat="server" ID="rblistComment">
        <Items>
            <dx:ListEditItem Text="Nouvelle information" Value="0" />
            <dx:ListEditItem Text="Correction de valeurs" Value="1" />
            <dx:ListEditItem Text="Autre" Value="2" />
        </Items>
        <ClientSideEvents SelectedIndexChanged="rblistComment_SelectIndexChanged" />
    </dx:ASPxRadioButtonList>
    
    复杂的多字段验证 任何需要来自多个字段的数据的验证都不应在客户端上处理。请在C#中执行此操作。尝试将其拼凑在一起
    <dx:ASPxRadioButtonList runat="server" ID="rblistComment">
        <Items>
            <dx:ListEditItem Text="Nouvelle information" Value="0" />
            <dx:ListEditItem Text="Correction de valeurs" Value="1" />
            <dx:ListEditItem Text="Autre" Value="2" />
        </Items>
        <ClientSideEvents SelectedIndexChanged="rblistComment_SelectIndexChanged" />
    </dx:ASPxRadioButtonList>
    
    function rblistComment_SelectIndexChanged(s,e) {
    
    var btnOk = eval($("[id$=btnOK]").attr("id"));
    var txtCommentPopup = eval($("[id$=txtCommentPopup]").attr("id"));
    
    btnOk.SetEnabled(s.GetValue() != null);
    txtCommentPopup.SetVisible(s.GetValue() == '2');
    
    const string csname = "ClientEvents";
    const string csurl = "~/js/EtudeCliniqueScript/ClientEvents.js";
    Type cstype = this.GetType();
    
    ClientScriptManager cs = Page.ClientScript;
    
    if (!cs.IsClientScriptIncludeRegistered(cstype, csname))
    {
        cs.RegisterClientScriptInclude(cstype, csname, ResolveClientUrl(csurl));
    }