ASP.NET Generic Handler not getting called after .NET 3.5 to .NET 4.0 upgrade

≯℡__Kan透↙ 提交于 2019-12-07 21:19:00

问题


This old title describes the visible issue, but the new title describes the root cause issue a little better. I'm still not sure why the ASHX isn't getting called, so I'm still looking for an answer. I have a workaround for now by hard coding the API descriptor (Ext.app.REMOTING_API variable). I got that JSON object (Ext.app.REMOTING_API variable) from the DirectProxy "provider" returned variable, from the original code running .NET 3.5. I just used an online JavaScript beautifier to make it look beautiful (so you can read it, instead of being on a single line).

Old Title: ExtJS 3 Ext.Direct proxy error: Uncaught TypeError: Cannot read property 'events' of undefined

I just upgraded the extdirect4dotnet project from .NET 3.5 to .NET 4.0. That project and a sample project can be found here https://code.google.com/p/extdirect4dotnet/. When I did this, I had to temporarily copy the Web.Config file when I changed the project version. I fixed the parameter list of two override methods that was due to inheriting a class in JSON.NET found at http://json.codeplex.com/SourceControl/latest#readme.txt. I also fixed the way DLL references were being made in both projects. I then replaced all occurances of "3.5" to "4.0" in the Web.Config.

Unfortunately, this project uses ExtJs 3.0.0, not ExtJs 4.2.* which is the framework version I'm implementing the Ext.Direct proxy for with this .NET server-side stack (extdirect4dotnet) with. So it still uses some old syntax. Below I'm trying to figure out how to fix a particular error after the .NET upgrade. It's still using ExtJs 3.0.0. See "see this line" in the "addProvider" function to see the line it's failing on. When I debug this from JavaScript, "provider" is undefined. I guess it doesn't know how to get provider Ext.app.REMOTING_API after I upgraded this to .NET 4.0.

JavaScript error:

Uncaught TypeError: Cannot read property 'events' of undefined 

ExtJs code:

/*!
 * Ext JS Library 3.0.0
 * Copyright(c) 2006-2009 Ext JS, LLC
 * licensing@extjs.com
 * http://www.extjs.com/license
 */

...

 * </code></pre>
 * @param {Object/Array} provider Accepts either an Array of Provider descriptions (an instance
 * or config object for a Provider) or any number of Provider descriptions as arguments.  Each
 * Provider description instructs Ext.Direct how to create client-side stub methods.
 */
addProvider : function(provider){        
    var a = arguments;
    if(a.length > 1){
        for(var i = 0, len = a.length; i < len; i++){
            this.addProvider(a[i]);
        }
        return;
    }

    // if provider has not already been instantiated
    if(!provider.events){  // <========================= see this line
        provider = new Ext.Direct.PROVIDERS[provider.type](provider);
    }
    provider.id = provider.id || Ext.id();
    this.providers[provider.id] = provider;

    provider.on('data', this.onProviderData, this);
    provider.on('exception', this.onProviderException, this);


    if(!provider.isConnected()){
        provider.connect();
    }

    return provider;
},

Sample project JavaScript code:

Ext.Direct.addProvider(Ext.app.REMOTING_API); 

Screen shot of JavaScript debugger on "provider" object with .NET 3.5 implementation (before .NET upgrade)

(open in new window to see a larger image)

As a workaround, I've done the following to my js file and hard coded the provider (Ext.app.REMOTING_API variable). This is essentially a JSON object which is my API Descriptor. I captured the variable "provider" from the inherited ASHX code below when the sample project was configured with .NET 3.5. For some strange reason, my Generic Handler in ASP.NET is not getting called. The class the Generic Handler is inheriting from seems like normal .NET 4.0 Generic Handler (ASHX) code to me. I've pasted the HTML, ASHX and inherited ASHX below.

Ext.onReady(function () {

    Ext.app.REMOTING_API = {
        "type": "remoting",
        "id": "1",
        "url": "../directRouter.ashx",
        "actions": {
            "CallTypes": [{
                "name": "Echo",
                "len": 1,
                "formHandler": false
            }, {
                "name": "GetTime",
                "len": 0,
                "formHandler": false
            }, {
                "name": "UploadHttpRequestParam",
                "len": 1,
                "formHandler": true
            }, {
                "name": "UploadNamedParameter",
                "len": 1,
                "formHandler": true
            }, {
                "name": "SaveMethod",
                "len": 3,
                "formHandler": false
            }, {
                "name": "SaveMethod_Form",
                "len": 1,
                "formHandler": true
            }, {
                "name": "DateSample",
                "len": 2,
                "formHandler": false
            }],
            "TreeAction": [{
                "name": "getChildNodes",
                "len": 2,
                "formHandler": false
            }],
            "CRUDSampleMethods": [{
                "name": "create",
                "len": 1,
                "formHandler": false
            }, {
                "name": "read",
                "len": 1,
                "formHandler": false
            }, {
                "name": "update",
                "len": 2,
                "formHandler": false
            }, {
                "name": "destroy",
                "len": 1,
                "formHandler": false
            }, {
                "name": "reset",
                "len": 0,
                "formHandler": false
            }]
        }
    };


    Ext.Direct.addProvider(Ext.app.REMOTING_API);
    //Ext.Direct.addProvider();

    var Employee = Ext.data.Record.create([
        { name: 'firstname' },                  // map the Record's "firstname" field to the row object's key of the same name
        {name: 'job', mapping: 'occupation'}  // map the Record's "job" field to the row object's "occupation" key
    ]);

    var reader = new Ext.data.JsonReader({
        totalProperty: 'results',
        successProperty: 'success',
        idProperty: 'id',
        root: 'data'
    }, [
            { name: 'id' },
            { name: 'email', allowBlank: false },
            { name: 'first', allowBlank: false },
            { name: 'last', allowBlank: false }
        ]
    );
    var writer = new Ext.data.JsonWriter({
        returnJson: false,
        writeAllFields: true
    });

    var store = new Ext.data.DirectStore({
        api: {
            read: CRUDSampleMethods.read,
            create: CRUDSampleMethods.create,
            update: CRUDSampleMethods.update,
            destroy: CRUDSampleMethods.destroy
        },
        reader: reader,
        baseParams: { dummy: 'blubb' },
        writer: writer,     // <-- plug a DataWriter into the store just as you would a Reader
        paramsAsHash: true,
        batchSave: false,
        batch: false,
        prettyUrls: false,
        remoteSort: true,
        listeners: {
            load: function (result) {
            },
            loadexception: function () {

            },
            scope: this
        }
    });
    //

    var myPageSize = 10;

    var userColumns = [
        { header: "ID", width: 40, sortable: true, dataIndex: 'id' },
        { header: "Email", width: 100, sortable: true, dataIndex: 'email', editor: new Ext.form.TextField({}) },
        { header: "First", width: 50, sortable: true, dataIndex: 'first', editor: new Ext.form.TextField({}) },
        { header: "Last", width: 50, sortable: true, dataIndex: 'last', editor: new Ext.form.TextField({}) }
    ];
    Ext.onReady(function () {
        Ext.QuickTips.init();

        var userForm = new App.user.Form({
            renderTo: 'user-form',
            listeners: {
                create: function (fpanel, data) {   // <-- custom "create" event defined in App.user.Form class
                    var rec = new userGrid.store.recordType(data);
                    userGrid.store.insert(0, rec);
                }
            }
        });

        // create user.Grid instance (@see UserGrid.js)
        var userGrid = new App.user.Grid({
            renderTo: 'user-grid',
            store: store,
            columns: userColumns,
            bbar: new Ext.PagingToolbar({
                store: store,       // grid and PagingToolbar using same store
                displayInfo: true,
                pageSize: myPageSize,
                prependButtons: true,
                items: [
                    'text 1'
                ]
            }),
            listeners: {
                rowclick: function (g, index, ev) {
                    var rec = g.store.getAt(index);
                    userForm.loadRecord(rec);
                },
                destroy: function () {
                    userForm.getForm().reset();
                }
            }
        });
        setTimeout(function () {
            Ext.get('loading').remove();
            Ext.fly('loading-mask').fadeOut({
                remove: true
            });
            store.load({ params: {
                start: 0,          // specify params for the first page load if using paging
                limit: myPageSize,
                foo: 'bar'
            }
            });

        }, 250);
    });

});   // onready

HTML code:

...

<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css" />    
<script type="text/javascript" src="../ext/ext-base-debug.js"></script>     
<script type="text/javascript" src="../ext/ext-all-debug.js"></script>
<!-- directProxy.rfc was registred in the web.config -->
<script type="text/javascript" src="../directProxy.ashx"></script>

...

ASHX:

using System;

using System.Collections;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using ExtDirect4DotNet;

namespace WebApplication1
{
   /// <summary>
    /// Zusammenfassungsbeschreibung für $codebehindclassname$
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class directProxy : DirectProxy
    {
        public directProxy()
        {
            DirectProxy.routerUrl = "../directRouter.ashx";
        }

    }
}

Inherited ASHX found within ExtDirect4DotNet (code didn't change during .NET 4.0 upgrade):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Configuration;
using System.Web.Configuration;
using ExtDirect4DotNet;
using ExtDirect4DotNet.helper;

namespace ExtDirect4DotNet
{
    /// <summary>
    /// Represents the Proxy For Ext.Direct Comunication.
    /// Tha ProccessRequest Methode scanns all the available Assembly for Classes and Methods with the 
    /// Direct Attribute.
    /// </summary>
    public class DirectProxy : IHttpHandler
    {
        private static string url = "";
        public static string routerUrl {
            get { return url; }
            set { url = value; }
        }

        public static DirectProvider getDirectProviderCache(string apiNameSpace)
        {

            string routerUrl = (DirectProxy.routerUrl == "") ? ConfigurationCache.getRouterUrl() : DirectProxy.routerUrl;

            // set default namspace for the remoting API
            string apiNamespace = (apiNameSpace == null || apiNameSpace == "") ? "Ext.app.REMOTING_API" : apiNameSpace;


            DirectProviderCache cache = DirectProviderCache.GetInstance();
            DirectProvider provider;

            //After being configured, the provider should be cached.
            if (!cache.ContainsKey(apiNamespace + "/" + routerUrl))
            {
                provider = new DirectProvider(apiNamespace, routerUrl);
                provider.Configure(AppDomain.CurrentDomain.GetAssemblies());
                if (!cache.ContainsKey(apiNamespace + "/" + routerUrl))
                    cache.Add(apiNamespace + "/" + routerUrl, provider);
            }
            else
            {
                provider = cache[apiNamespace + "/" + routerUrl];
            }
            return provider;
        }

        public void ProcessRequest(HttpContext context)
        {


            // set default namspace for the remoting API
            string apiNamespace = "Ext.app.REMOTING_API";
            if (context.Request.Form["ns"] != null)
            {
                // if there is an namespace parameter, use it...
                apiNamespace = context.Request.Form["ns"].ToString();
            }
            DirectProvider provider = getDirectProviderCache(apiNamespace);

            context.Response.Write(provider.ToString());

            /*
            old code..


            // set the Response typ to javascript since the responce gets Parsed into an Script Tag
            context.Response.ContentType = "text/JavaScript";

            string rem = "{";
            rem += "url: \""+routerUrl+"\",";
            rem += "type:\"remoting\",";


            //string json = DirectProxyGenerator.generateDirectApi();
           //rem += json;
            rem += "};";

            rem = apiNamespace + ".REMOTING_API =" + rem;
            rem = "(function(){" + rem + "})();";

            context.Response.Write(rem);
           */
        }

        public bool IsReusable
        {
            get { return false; }
        }
    }
}

回答1:


Solved it finally for both IIS 6 and IIS 7, after reproducing the issue in IIS 7!!

The HTTP Handlers work on IIS 6 with .NET 3.5 and .NET 4.0. However, when you upgrade the framework to .NET 4.0, the HTTP Handlers break on IIS 7. In order to fix, you must do 4 things.

1.) change application pool .NET version from v2.0 to v4.0

2.) change application pool from Integrated to Classic

3.) change application pool from 64 bit to 32 bit

4.) replace the XML tag in the Web.Config. If you don't and you replace the "3.5.0.0" version for these lines with "4.0.0.0", it can corrupt IIS and throw this error.

Configuration file is not well-formed XML #2

.NET version 3.5 Web.Config configuration:

(notice the lowercase versus uppercase letters in the "PublicKeyToken" attribute value)

  <!--<configSections>
    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
        <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
          <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
          <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
          <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
          <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
  </configSections>-->

.NET version 4.0 Web.Config configuration:

  <configSections>
    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
        <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions,  Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere"/>
          <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
          <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
          <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
  </configSections>

Related to:

https://serverfault.com/questions/525443/how-to-uninstall-iis-from-windows-server-2008/525496#525496

Configuration file is not well-formed XML #2



来源:https://stackoverflow.com/questions/17779128/asp-net-generic-handler-not-getting-called-after-net-3-5-to-net-4-0-upgrade

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!