views:

1185

answers:

3

Hi,

We use the asp.net UpdatePanel and the ScriptManager/ScriptManagerProxy for ajax related functionality; reducing full page refreshes and calling WCF Services respectively. we also use jQuery and plugins for some parts of the UI.

We have had some issues with javascript library related conflicts, but have come across some posts indicating that there is a lot more overhead using the UpdatePanel.

I have found some limited reference to UFrame:

http://www.codeproject.com/KB/aspnet/uframe.aspx

www.codeplex.com/uframe

Is this a commercially viable replacement for the asp.net UpdatePanel?

We use a ScriptManagerProxy to reference WCF services and easily create and use a proxy to call the various WCF service methods.

Would using jQuery ajax be a more efficient solution here? We have got this working well on various browsers but now seem to be getting some security related issues (as seen in FF Firebug: Access to restricted URI denied" code: "1012) which seem to have started since using jQuery a lot more.

Is it possible/viable to not use ASP.NET Ajax at all?

+1  A: 

I was using Ajax exclusively until I got tired of the sheer innefficiency of the update panels. They work, but it is so darn slow when you are trying to do anything real on a website. I had pages with a few update panels and they would simply take seconds to refresh.

So I moved to jQuery using webservices for the data access. It was a great move. Now the pages load faster. There is a little bit of a loss of convinience since I am trying to completly get rid of the scriptmanager, but the following bit of javascript made calling the services a lot easier. Coupled with some restful wcf services, it works like a charm. I've converted entire page to a windows like editing system using only javascript and restful service.

Anyway, here is some code to help calling services in jQuery

// *** Service Calling Proxy Class
function serviceProxy(serviceUrl) {
    var _I = this;
    this.serviceUrl = serviceUrl;

    // *** Call a wrapped object
    this.invoke = function(method, data, callback, error, bare) {
        // *** Convert input data into JSON - REQUIRES Json2.js
        var json = JSON2.stringify(data);

        // *** The service endpoint URL        
        var url = _I.serviceUrl + method;

        $.ajax({
            url: url,
            data: json,
            type: "POST",
            processData: false,
            contentType: "application/json",
            timeout: 10000,
            dataType: "text",  // not "json" we'll parse
            success:
                    function(res) {
                        if (!callback) return;

                        // *** Use json library so we can fix up MS AJAX dates
                        var result = JSON2.parse(res);

                        // *** Bare message IS result
                        if (bare)
                        { callback(result); return; }

                        // *** Wrapped message contains top level object node
                        // *** strip it off
                        for (var property in result) {
                            callback(result[property]);
                            break;
                        }
                    },
            error: function(xhr) {
                if (!error) return;
                if (xhr.responseText) {
                    var err = null;
                    try{ var err = JSON2.parse(xhr.responseText); }
                    catch(e) { err = xhr.responseText;}

                    if (err)
                        error(err);
                    else
                        error({ Message: "Unknown server error." })
                }
                return;
            }
        });
    }
}
if (!this.JSON2) {
    JSON2 = function() {
        function f(n) { return n < 10 ? '0' + n : n; }
        var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g, gap, indent, meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' }, rep; function quote(string) {
            return escapeable.test(string) ? '"' + string.replace(escapeable, function(a) {
                var c = meta[a]; if (typeof c === 'string') { return c; }
                c = a.charCodeAt(); return '\\u00' + Math.floor(c / 16).toString(16) +
(c % 16).toString(16);
            }) + '"' : '"' + string + '"';
        }
        function str(key, holder) {
            var i, k, v, length, mind = gap, partial, value = holder[key]; if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); }
            if (typeof rep === 'function') { value = rep.call(holder, key, value); }
            switch (typeof value) {
                case 'string': return quote(value); case 'number': return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': return String(value); case 'object': if (!value) { return 'null'; }
                    if (value.toUTCString)
                    { var xx = '"\\/Date(' + value.getTime() + ')\\/"'; return xx; }
                    gap += indent; partial = []; if (typeof value.length === 'number' && !(value.propertyIsEnumerable('length'))) {
                        length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; }
                        v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v;
                    }
                    if (typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value, rep); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { for (k in value) { v = str(k, value, rep); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } }
                    v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v;
            } 
        }
        return { stringify: function(value, replacer, space) {
            var i; gap = ''; indent = ''; if (space) { if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } } else if (typeof space === 'string') { indent = space; } }
            if (!replacer) {
                rep = function(key, value) {
                    if (!Object.hasOwnProperty.call(this, key)) { return undefined; }
                    return value;
                };
            } else if (typeof replacer === 'function' || (typeof replacer === 'object' && typeof replacer.length === 'number')) { rep = replacer; } else { throw new Error('JSON.stringify'); }
            return str('', { '': value });
        }, parse: function(text, reviver) {
            var j; function walk(holder, key) {
                var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } }
                return reviver.call(holder, key, value);
            }
            if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { var regEx = /(\"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}.*?\")|(\"\\*\/Date\(.*?\)\\*\/")/g; text = text.replace(regEx, this.regExDate); j = eval('(' + text + ')'); return typeof reviver === 'function' ? walk({ '': j }, '') : j; }
            throw new SyntaxError('JSON.parse');
        }, regExDate: function(str, p1, p2, offset, s) {
            str = str.substring(1).replace('"', ''); var date = str; if (/\/Date(.*)\//.test(str)) { str = str.match(/Date\((.*?)\)/)[1]; date = "new Date(" + parseInt(str) + ")"; }
            else { var matches = str.split(/[-,:,T,Z]/); matches[1] = (parseInt(matches[1], 0) - 1).toString(); date = "new Date(Date.UTC(" + matches.join(",") + "))"; }
            return date;
        }, quote: quote
        };
    } ();
}

The usage is like this:

    var manageProxy = new serviceProxy("/WebServices/ResultStructuresService.svc/");
    manageProxy.invoke("SomeFunction",
        { someparam: somevalue },
        function(message) {

            if (!message) {
                return;
            }
            // the json parameters should be encode to prevent that attack 
            if (message && message.length > 0) {
                // do something with the response
                _allowedTypes = message;
            }
        },
        function(error) {
            $.jGrowl(error.Detail, { header: "Oops!", life: 8000 });
        });
ADB
Thanks, I had an incling that ScriptManager makes things easier and that I would need to add some code to create the 'proxy'; Is this your code, or does this belong to a supported plugin that I could use? Also I have just started using WCF Services in a new project rather than standard WebServices, What makes them 'restful'? Also is calling these WCF services limited to the same domain, unlike standard webservices?
Mark Redman
The code originated from Rick Stralh's great series on webservices and jQuery: http://www.west-wind.com/weblog/posts/324917.aspx. However, I've modified it to handle more errors. A restful service is a different philosophy on how to build a webservice. The only important thing is to remember to make the service output to JSON. That is valid for any webservice you want to use without the scripmanager. There shouldn't be a domain limitation on WCF services calls either.
ADB
ok thats great! Will get an example working (...jGrowl looks interesting too)
Mark Redman
+1  A: 

In the long run, you're better off using jQuery. VS2010 ships with jQuery out of the box, I'd recommend using it, you won't regret it. It's a lot cleaner, lots of plugins out there and it's very efficient. Once you get used it, it's easy to transfer the knowledge to other platforms, too.

JR
@JR: Thanks for the response. We have moved to ASP.NET MVC and are using jQuery, a good match and keeps things basic...
Mark Redman
A: 

I have a question regarding serviceProxy. I built my website. At first it is local and calls to my WCF on a server using serviceProxy. It's simple - calls a list of the United States and populates a HTML select drop down.

I preloaded jquery.js and serviceproxy.js in the asp script manager on the master page. In the page behind where I call the WCF, I load the external callusa.js file - in that call callusa.js file I included a reference to jquery.js /// `/jquery.js'

It works fine locally - but when I deploy my application, I get an undefined error. It seems to be failing on the global variable serviceProxy and I wonder if anyone else has the same problem? If you have a sample project with a master page I'd be grateful because I think I'm missing something when it comes to deploying the project....

glenn