GVKun编程网logo

高效管理DWR中的ScriptSession,ScriptSessionLintener

11

如果您想了解高效管理DWR中的ScriptSession,ScriptSessionLintener的相关知识,那么本文是一篇不可错过的文章,我们将为您提供关于ActionScriptWorkerMe

如果您想了解高效管理DWR中的ScriptSession,ScriptSessionLintener的相关知识,那么本文是一篇不可错过的文章,我们将为您提供关于ActionScript Worker Message Passing is Slow(ActionScript 线程间通信速度的提升建议 )、API(总限制):Lcom/android/org/conscrypt/ConscryptEngineSocket;->setUseSessionTickets(Z)V、ASP.NET in C#,ClientScript.RegisterStartupScript与ClientScript.RegisterClientScriptBlock用法之己见、asp.net – 有一个ClientScriptManager.RegisterClientScriptInclude等效的CSS的有价值的信息。

本文目录一览:

高效管理DWR中的ScriptSession,ScriptSessionLintener

高效管理DWR中的ScriptSession,ScriptSessionLintener

当我们在使用DWR的反向AJax是,每次页面的刷新都会产生一个ScriptSession(SS),但是我们确无从对过期的SS进行即使的销毁,虽然可以通过在每个页面访问时,自动执行某个方法,来销毁那些当前用户的非有效SS,但是这样也使得我们在代码管理上带来非常麻烦的问题.

DWR3的诞生终于给我们提供了ScritpSessionLintener(SSL)接口

本文,主要讲解如何使用ScriptSession接口.

DWR支持在Web.XML当中,配置扩展.

Xml代码
  1. <init-param>
  2. param-name>*</param-value>

但是,经过几次的实验和摸索,SSL在当中配置后,管理器会进行有效构造,但是SS在创建和销毁时,并不会执行继承了ScriptSessionListner类的相关方法.(或许是我自己项目的问题.)

经过自己的研究发现,在ScriptSessionManager类中,包含了AddScriptSessionListener方()法.这样给使用SSL带来了方便

我们只需要在Web.XML文件中配置一个自定义的ScrptSessionManager

Java代码
    publicclassCustomScriptSessionManagerextendsorg.directwebremoting.impl.DefaultScriptSessionManager{
  1. publicCustomScriptSessionManager(){
  2. try{
  3. this.addScriptSessionListener(newCustomScriptSessionListener());
  4. }catch(Exceptione){
  5. e.printstacktrace();
  6. }
  7. }

*CustomScriptSessionListener为一个实现了ScriptSessionListener接口的实体类.

通过这种方式,将SS管理程序注射近SSM内,让管理器在SS状态发生变化时,即使通过SSL进行处理

如何使得每个用户的SS都是新鲜的,每个人都有自己的方法,我在自己的管理程序内使用一个

将每个用户的Session内存放当前ScriptSession进行绑定,当用户生成一个新的ScriptSession时,根据用户的Session,并且将旧的ScriptSession进行主动销毁,并更新Session.

这样,我们随着高效的保证每个用户只有一个ScriptSession存在于内存当中,使得我们的程序更加高效.

packagecom.dwr;
  • importjava.util.Collection;
  • importjava.util.Iterator;
  • importjava.util.Vector;
  • importjavax.servlet.http.HttpServletRequest;
  • importjavax.servlet.http.HttpSession;
  • importorg.directwebremoting.ScriptSession;
  • importorg.directwebremoting.ServerContextFactory;
  • importorg.directwebremoting.WebContext;
  • importorg.directwebremoting.WebContextFactory;
  • importorg.directwebremoting.event.ScriptSessionEvent;
  • importorg.directwebremoting.event.ScriptSessionListener;
  • importorg.dom4j.Document;
  • importorg.dom4j.Element;
  • importorg.dom4j.io.SAXReader;
  • /**
  • *在线ScriptSession(SSL)监听管理器.
  • *在SSL中,每当DWR工厂在生成一个新的ScriptSession(SS)时,将被SSL捕获
  • *SSL对捕获的SS进行初始化赋值
  • *其中在SS属性中的SessionLabel.CurrentSesionID赋予当前用户的SessinID
  • *并在改用户的Session属性中的SessionLabel.CurrentScriptSessionID赋予当前的SSL
  • *然后在SessionLabel.CurrentPage中赋予当前SS的操作界面地址
  • *
  • *并且开始激活SSL插件中的sessionCreated方法
  • *当
  • *@author熊浩华-ibmsz
  • *2009-8-18:下午03:11:55-
  • */
  • classCustomScriptSessionListenerimplementsScriptSessionListener{
  • staticfinalHttpSessionLabelSessionLabel=newHttpSessionLabel();
  • privateCollection<IListenerMessage>collection=null;
  • publicCustomScriptSessionListener()throwsException{
  • System.out.println("开始构造SSL");
  • collection=newVector<IListenerMessage>();
  • SAXReaderreader=newSAXReader();
  • Documentdocument=reader.read(this.getClass().getResource("ScriptSessionListener.xml"));
  • ElementrootElement=document.getRootElement();
  • Iteratorit=rootElement.elementIterator("listener");
  • while(it.hasNext()&&it!=null){
  • Elementelement=(Element)it.next();
  • Stringclasspath=element.getTextTrim();
  • if(classpath==null||classpath.trim().equals("")){
  • continue;
  • Classcls=Class.forName(classpath);
  • Objectobject=cls.newInstance();
  • if(objectinstanceofIListenerMessage){
  • this.collection.add((IListenerMessage)object);
  • @SuppressWarnings("deprecation")
  • finalvoidsessionCreated(ScriptSessionEventsSessionEvent){
  • //System.out.println("创建新的ScriptSession时执行");
  • ScriptSessionscriptSession=sSessionEvent.getSession();//获取新创建的SS
  • WebContextwebContext=WebContextFactory.get();
  • HttpServletRequesthttpServletRequest=webContext.getHttpServletRequest();
  • HttpSessionhttpSession=httpServletRequest.getSession();//获取构造SS的用户的HttpSession
  • ScriptSessioncurrSession=(ScriptSession)httpSession.getAttribute(SessionLabel.getCurrentScriptSessionID());
  • if(currSession!= currSession.invalidate();
  • for(IListenerMessagemessage:this.collection){
  • message.sessionCreated(sSessionEvent);
  • httpSession.setAttribute("DWR3.CurrPath",scriptSession.getPage());
  • httpSession.setAttribute("DWR3.CurrScriptSession",scriptSession);
  • Collection<ScriptSession>sSCollection=webContext.getScriptSessionsByPage(scriptSession.getPage());
  • for(ScriptSessionsession:sSCollection){
  • if(session.getAttribute(SessionLabel.getCurrentSesionID())== message.sendCreateMessage(scriptSession,session);
  • scriptSession.setAttribute(SessionLabel.getCurrentSesionID(),httpSession.getId());
  • voidsessionDestroyed(ScriptSessionEventsSessionEvent){//销毁一个ScriptSession时执行
  • ScriptSessionscriptSession=sSessionEvent.getSession();
  • /*
  • Objectusername=(Object)scriptSession.getAttribute(SessionLabel.getCurrentScritpUserName());
  • if(username==null){
  • username="";
  • }
  • message.sessionDestroyed(sSessionEvent);
  • Collection<ScriptSession>collection=ServerContextFactory.get().getScriptSessionsByPage(scriptSession.getPage());
  • for(ScriptSessionsession:collection){
  • StringscritpAttrID=(String)session.getAttribute(SessionLabel.getCurrentSesionID());
  • if(scritpAttrID!= message.sendDestroyMessage(scriptSession,85); font-weight:bold">classHttpSessionLabel{
  • privatefinalStringCurrentScriptSessionID="DWR3.CurrScriptSession";
  • finalStringCurrentScritpUserName="DWR.Chat.UserName";
  • finalStringCurrentSesionID="DWR3.CurrSessionID";
  • finalStringCurrentPage="DWR3.CurrPath";
  • *获取当前SessionScript的在线页面
  • *@returncurrentPage
  • publicStringgetCurrentPage(){
  • returnCurrentPage;
  • *获取Session中的当前ScriptSession的ID
  • *@returncurrentScriptSessionID
  • publicStringgetCurrentScriptSessionID(){
  • returnCurrentScriptSessionID;
  • *获取当前用户名称
  • *@returncurrentScritpUserName
  • publicStringgetCurrentScritpUserName(){
  • returnCurrentScritpUserName;
  • *获取ScriptSession中的HttpSessionID
  • *@returncurrentSesionID
  • publicStringgetCurrentSesionID(){
  • returnCurrentSesionID;
  • }
  • 以上代码是从一个通过DWR实现的及时在线聊天系统中抽取出来的ScriptSession监听器.

    红色标注部分为管理SS的程序段

    全案例源代码下载

    ActionScript Worker Message Passing is Slow(ActionScript 线程间通信速度的提升建议 )

    ActionScript Worker Message Passing is Slow(ActionScript 线程间通信速度的提升建议 )

    Originaly From: http://jacksondunstan.com/articles/2390

    Since Flash Player 11.4 was released we have finally been given the ability to run multiple threads of AS3 code to take advantage of modern multi-core cpus. However,when we start writing this multi-threaded code we immediately run into the requirement to coordinate the threads by passing messages between them. As it turns out,this is quite slow in AS3. Read on for the performance analysis.

    The following test app performs a very simple task in two ways. The main thread passes a series of integers to a worker thread and the worker thread adds those integers together to compute their sum. Two ways of accomplishing this task are used. The first way passes 1000 individual messages to the worker thread,each with an integer to add. A final message is passed to tell the worker to pass the sum back to the main thread and clear for the next test. The second way of computing the sum creates aByteArray with the shareable flag set to true. ThisByteArray is then filled with all of the integers to sum and sent to the worker thread. The worker thread extracts these integers,adds them together,and passes a message back with the sum.

    These two ways have been designed such that one passes a lot of messages and the other only passes one. Check out the source code for details.

     

    package { import flash.display.Sprite; import flash.events.Event; import flash.utils.getTimer; import flash.utils.ByteArray; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.system.Worker; import flash.system.WorkerDomain; import flash.system.WorkerState; import flash.system.MessageChannel; public class MessageChannelTest extends Sprite { private var logger:TextField = new TextField(); private function row(...cols): void { logger.appendText(cols.join(",")+"\n"); } private var mainToWorker:MessageChannel; private var mainToWorkerBytes:MessageChannel; private var mainToWorkerClear:MessageChannel; private var workerToMain:MessageChannel; private var worker:Worker; private var REPS:int = 100000; private var beforeTime:int; private var sum:int; private var correctSum:int; public function MessageChanneltest() { logger.autoSize = TextFieldAutoSize.LEFT; addChild(logger); if (Worker.current.isPrimordial) { startMainThread(); } else { startWorkerThread(); } } private function startMainThread(): void { worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes); mainToWorker = Worker.current.createMessageChannel(worker); worker.setSharedProperty("mainToWorker",mainToWorker); mainToWorkerBytes = Worker.current.createMessageChannel(worker); worker.setSharedProperty("mainToWorkerBytes",mainToWorkerBytes); mainToWorkerClear = Worker.current.createMessageChannel(worker); worker.setSharedProperty("mainToWorkerClear",mainToWorkerClear); workerToMain = worker.createMessageChannel(Worker.current); workerToMain.addEventListener(Event.CHANNEL_MESSAGE,onWorkerToMainDirect); worker.setSharedProperty("workerToMain",workerToMain); worker.start(); for (var i:int = 0; i < REPS; ++i) { correctSum += i; } row("Type","Time","Correct?"); sum = 0; beforeTime = getTimer(); for (i = 0; i < REPS; ++i) { mainToWorker.send(i); } mainToWorkerClear.send(true); } private function startWorkerThread(): void { mainToWorker = Worker.current.getSharedProperty("mainToWorker"); mainToWorkerBytes = Worker.current.getSharedProperty("mainToWorkerBytes"); mainToWorkerClear = Worker.current.getSharedProperty("mainToWorkerClear"); workerToMain = Worker.current.getSharedProperty("workerToMain"); mainToWorker.addEventListener(Event.CHANNEL_MESSAGE,onMainToWorker); mainToWorkerBytes.addEventListener(Event.CHANNEL_MESSAGE,onMainToWorkerBytes); mainToWorkerClear.addEventListener(Event.CHANNEL_MESSAGE,onMainToWorkerClear); } private function onMainToWorker(event:Event): void { sum += mainToWorker.receive(); } private function onMainToWorkerBytes(event:Event): void { var bytes:ByteArray = mainToWorkerBytes.receive(); bytes.position = 0; var numInts:int = bytes.length / 4; var sum:int; for (var i:int; i < numInts; ++i) { sum += bytes.readInt(); } workerToMain.send(sum); } private function onMainToWorkerClear(event:Event): void { workerToMain.send(sum); sum = 0; } private function onWorkerToMainDirect(event:Event): void { sum = workerToMain.receive(); var afterTime:int = getTimer(); row("Direct",(afterTime-beforeTime),(sum==correctSum)); workerToMain.removeEventListener(Event.CHANNEL_MESSAGE,onWorkerToMainDirect); workerToMain.addEventListener(Event.CHANNEL_MESSAGE,onWorkerToMainBytes); var bytes:ByteArray = new ByteArray(); bytes.shareable = true; bytes.length = REPS*4; bytes.position = 0; sum = 0; beforeTime = getTimer(); for (var i:int; i < REPS; ++i) { bytes.writeInt(i); } mainToWorkerBytes.send(bytes); } private function onWorkerToMainBytes(event:Event): void { sum = workerToMain.receive(); var afterTime:int = getTimer(); row("ByteArray",(sum==correctSum)); } } }


     

    Run the test

    I ran this test in the following environment:

    • Release version of Flash Player 11.8.800.170
    • 2.3 Ghz Intel Core i7
    • Mac OS X 10.8.5
    • ASC 2.0.0 build 353981 (-debug=false -verbose-stacktraces=false -inline -optimize=true)

    And here are the results I got:

    The ByteArray version is clearly leaps and bounds faster than the direct version that passes individual messages. In this test environment at least,each message is taking 0.02359 milliseconds. A mere 50 messages would eat up a whole millisecond of this relatively-fast cpu,probably far too much for a complex game that’s otherwise busy with 3D graphics,physics,and so forth. If you can,it’s much quicker to bundle up these messages into aByteArray marked shareable and send them all over at once.

    API(总限制):Lcom/android/org/conscrypt/ConscryptEngineSocket;->setUseSessionTickets(Z)V

    API(总限制):Lcom/android/org/conscrypt/ConscryptEngineSocket;->setUseSessionTickets(Z)V

    如何解决API(总限制):Lcom/android/org/conscrypt/ConscryptEngineSocket;->setUseSessionTickets(Z)V?

    在应用发布之前,我在 Google Play 中遇到了以下错误。 你能帮忙解决吗?也许我应该更新一些库?

    接口API(总限制):Lcom/android/org/conscrypt/ConscryptEnginesocket;->setHostname(Ljava/lang/String;)V

    StrictMode policy violation: android.os.strictmode.NonSdkApiUsedViolation: Lcom/android/org/conscrypt/ConscryptEnginesocket;->setUseSessionTickets(Z)V
        at android.os.StrictMode.lambda$static$1(StrictMode.java:416)
        at android.os.-$$Lambda$StrictMode$lu9ekkHJ2HMz0jd3F8K8MnhenxQ.accept(UnkNown Source:2)
        at java.lang.class.getDeclaredMethodInternal(Native Method)
        at java.lang.class.getPublicmethodRecursive(Class.java:2079)
        at java.lang.class.getmethod(Class.java:2066)
        at java.lang.class.getmethod(Class.java:1693)
        at okhttp3.internal.platform.OptionalMethod.getPublicmethod(OptionalMethod.java:164)
        at okhttp3.internal.platform.OptionalMethod.getmethod(OptionalMethod.java:149)
        at okhttp3.internal.platform.OptionalMethod.invokeOptional(OptionalMethod.java:66)
        at okhttp3.internal.platform.OptionalMethod.invokeOptionalWithoutCheckedException(OptionalMethod.java:86)
        at okhttp3.internal.platform.Androidplatform.configureTlsExtensions(Androidplatform.java:122)
        at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:314)
        at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:283)
        at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:168)
        at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
        at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
        at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
        at okhttp3.RealCall.execute(RealCall.java:92)
        at com.google.firebase.crashlytics.internal.network.HttpRequest.execute(HttpRequest.java:129)
        at com.google.firebase.crashlytics.internal.settings.network.DefaultSettingsspiCall.invoke(DefaultSettingsspiCall.java:86)
        at com.google.firebase.crashlytics.internal.settings.SettingsController$1.then(SettingsController.java:200)
        at com.google.firebase.crashlytics.internal.settings.SettingsController$1.then(SettingsController.java:193)
        at com.google.android.gms.tasks.zzo.run(com.google.android.gms:play-services-tasks@@17.1.0:2)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at com.google.firebase.crashlytics.internal.common.ExecutorUtils$1$1.onRun(ExecutorUtils.java:60)
        at com.google.firebase.crashlytics.internal.common.BackgroundPriorityRunnable.run(BackgroundPriorityRunnable.java:27)
        at java.lang.Thread.run(Thread.java:923)
    

    解决方法

    Logcat 暗示您使用的是非 sdk api,根据文档 https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces

    ASP.NET in C#,ClientScript.RegisterStartupScript与ClientScript.RegisterClientScriptBlock用法之己见

    ASP.NET in C#,ClientScript.RegisterStartupScript与ClientScript.RegisterClientScriptBlock用法之己见

    ClientScript.RegisterStartupScript:
    http://msdn.microsoft.com/zh-cn/library/system.web.ui.clientscriptmanager.registerstartupscript(v=vs.80)
    ClientScript.RegisterClientScriptBlock:
    http://msdn.microsoft.com/zh-cn/library/system.web.ui.clientscriptmanager.registerclientscriptblock(v=vs.80).aspx
    ASP.NET中,可以使用这两个方法从后台向前台注册JavaScript脚本;
    这两个方法,各自都有两个重载的版本,个人推荐始终使用四个参数的版本,本文基于四个参数的版本:
    public void RegisterStartupScript(Type type, string key, string script, bool addScriptTags);
    public void RegisterClientScriptBlock(Type type, string key, string script, bool addScriptTags);
    如果addScriptTags==true,那么script会被包含在<script></script>元素块中;
    如果addScriptTags==false,此时这两个方法相当于三个参数的版本,<script></script>元素块需自己写;
    另外,如果想通过注册脚本的方式,在页面上输出html元素(如<h1>标题</h1>),可以把addScriptTags设置为false,在script中写html元素,例如:
    ClientScript.RegisterClientScriptBlock(Page.GetType(), "write", "<h1>标题一</h1>", false);
    当然了,不推荐这种做法了,因为太不灵活了,RegisterClientScriptBlock写的html元素只能在页面的顶部,RegisterStartupScript写的html元素只能在页面的底部;比较灵活的做法是,使用JavaScript操作DOM元素。
    好了,来说说RegisterClientScriptBlock和RegisterStartupScript的不同点吧:

    1. RegisterClientScriptBlock注册的脚本在<form>元素的后面,而RegisterStartupScript注册的脚本在</form>元素的前面:
    复制代码
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ClientScript.RegisterClientScriptBlock(Page.GetType(), "", "alert(''RegisterClientScriptBlock'');", true);
            ClientScript.RegisterStartupScript(Page.GetType(), "", "alert(''RegisterStartupScript'');", true);
        }
    }
    复制代码
    生成的html:
    复制代码
    <form method="post" action="Default.aspx" id="form1">
    <div>
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE2MTY2ODcyMjlkZFL5WzOc4Lk3midVVH7bOliUF/+AQZAXgy6DDne32SJ1" />
    </div>
     
    <script type="text/javascript"> 
    //<![CDATA[
    alert(''RegisterClientScriptBlock'');//]]>
    </script>
     
        <div>
        </div>
     
    <script type="text/javascript"> 
    //<![CDATA[
    alert(''RegisterStartupScript'');//]]>
    </script>
    </form>
    复制代码
    生成的html源代码清楚的展现了注册的脚本在页面上的位置;
    说明:生成的html源代码中,紧跟在<form>后,在RegisterClientScriptBlock注册的脚本前的内容(可能还有其他的),是ASP.NET为了实现自身功能所必须的由系统自动生成的,如果撇开这些内容,可以认为RegisterClientScriptBlock生成的脚本是紧跟在<form>元素后的。

    2. 因为RegisterClientScriptBlock与RegisterStartupScript注册的脚本的位置不同,导致两者使用的场合也有所不同:
    1> RegisterClientScriptBlock注册的脚本是在DOM元素未完全加载前执行的,这就导致了,它无法访问页面中几乎所有的html元素;所以RegisterClientScriptBlock适合写JavaScript函数、警告(在用户点击“确定”之前,页面为空白);
    2> RegisterStartupScript注册的脚本也是在DOM元素未完全加载前执行的,可是与RegisterClientScriptBlock不同的是,页面上的大部分DOM元素它都可以访问;所以RegisterStartupScript不太适合写JavaScript函数,可能调用它写的函数的时候,函数还没加载到页面上呢;
    RegisterStartupScript也可以用来写警告,此时,即使用户没有点击“确定”按钮,也可以看到页面的内容;
    ※ 关于RegisterStartupScript写的警告(alert),如果</form>后面有JavaScript脚本(直接硬编码在页面上的),且此脚本是控制页面呈现样式的,那么在用户点击警告框中的“确定”按钮前,页面的呈现可能会非预期;

    3. 如果注册的脚本的执行依赖于页面上的元素,或为了显示出预期的效果(上面提到的用户未点击“确定”按钮,页面呈现非预期),可以结合window.onload事件,如果使用了JQuery,可以把脚本包含在:
    $(document).ready(function() {
    // 这里
    });

    4. 最后说一下RegisterStartupScript和RegisterClientScriptBlock函数的第二个参数key吧:
    在页面加载或处理请求的过程中,执行了若干次RegisterStartupScript和RegisterClientScriptBlock方法,如果没有给该函数指定key,即key="",或key重复,因为相同key的脚本只会注册一次,重复注册的脚本会被忽略,如果出现了某些脚本未注册的情况,此时就需要检查是否出现了重复的key;RegisterStartupScript和RegisterClientScriptBlock的key可以重复,因为是不同的方法嘛!~
    可以通过:
    public bool IsStartupScriptRegistered(Type type, string key);
    public bool IsClientScriptBlockRegistered(Type type, string key);
    来检查是否注册了相应key的脚本,避免重复注册:
    ClientScript.RegisterStartupScript(Page.GetType(), "alert", "alert(''RegisterStartupScript'');", true);
    if (!ClientScript.IsStartupScriptRegistered(Page.GetType(), "alert"))
    {
        ClientScript.RegisterStartupScript(Page.GetType(), "alert", "alert(''RegisterStartupScript_2'');", true);
    }
    上面的示例只是为了讲解IsStartupScriptRegistered的用法,实际使用中,没有谁会写这么小白的用法!~
    如果可以保证在页面加载或处理请求的过程中,只会调用一次RegisterStartupScript和RegisterClientScriptBlock方法,可以不指定key;
    例如,处理表单数据,某个字段不符合要求时,提示:
    if (string.IsNullOrEmpty(txtInput.Value.Trim()))
    {
        ClientScript.RegisterStartupScript(Page.GetType(), "", "alert(''不可以为空!'');", true);
        return;
    }

    asp.net – 有一个ClientScriptManager.RegisterClientScriptInclude等效的CSS

    asp.net – 有一个ClientScriptManager.RegisterClientScriptInclude等效的CSS

    ClientScriptManager.RegisterClientScriptInclude方法允许您使用Page对象注册JavaScript参考(检查重复项).

    CSS引用的方法是否相当?

    类似的问题适用于ClientScriptManager.RegisterClientScriptBlock和ClientScriptManager.RegisterClientScriptResource

    解决方法

    简答:否你肯定会滚动自己的功能(正如CMPalmer所建议的),采用CSS嵌入式资源(如Gulzar所说),并将它们嵌入页面.

    作为一个最佳实践的事情,虽然,我不知道为什么你会这样做.如果您正在制作具有很多CSS样式的可重复使用的控件,我的建议是将类名称硬编码为符合标准的控件输出,并附带一个建议的样式表.这样您的用户/客户可以选择覆盖您的建议样式以满足他们的需求,一般来说,他们可以根据自己的需要管理自己的CSS设置.

    分离风格与标记是一件好事 – 您已经走下了正确的道路,避免了各种内置的ASP.NET风格属性,但您应该把它一直保留下来,使其保持在.dll之外.

    我们今天的关于高效管理DWR中的ScriptSession,ScriptSessionLintener的分享已经告一段落,感谢您的关注,如果您想了解更多关于ActionScript Worker Message Passing is Slow(ActionScript 线程间通信速度的提升建议 )、API(总限制):Lcom/android/org/conscrypt/ConscryptEngineSocket;->setUseSessionTickets(Z)V、ASP.NET in C#,ClientScript.RegisterStartupScript与ClientScript.RegisterClientScriptBlock用法之己见、asp.net – 有一个ClientScriptManager.RegisterClientScriptInclude等效的CSS的相关信息,请在本站查询。

    本文标签:

    上一篇ecshop后台ajax无刷新修改商品数量原理分析(ecshop有哪些bug)

    下一篇DWR中获取Session,Request,Response等信息(dw里面获取验证码怎么做)