Recently about Web Development
$.get $.post $.loadASP .Net has, what they tout as ultra simple, the update panel for ajax post backs to the server. But, this tool is not as simple as it seems. While deceptively simple to stick on a page and wire up to the code behind, it takes much more to make this tool work.
const string scriptResourceHandler = "System.Web.Handlers.ScriptResourceHandler,System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; const string scripthandlerfactory = "ScriptHandlerFactory"; const string scripthandlerfactoryappservice = "ScriptHandlerFactoryAppService"; const string scriptresource = "ScriptResource"; const string scriptModuleAssembly = "System.Web.Handlers.ScriptModule,System.Web.Extensions,Version=3.5.0.0,Culture=Neutral,PublicKeyToken=31bf3856ad364e35"; const string webScriptAssembly = "System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"; const string webExtensionAssembly = "System.Web.Extensions,Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"After you have done that, or just copied the above assemblies, those assemblies have to be added to the web.config. That is where the SPWebConfigModification comes into play. First, you'll want to clear the modifications otherwise, modifications might appear for items that are long gone.
webApp.WebConfigModifications.Clear();After that is set up, there is quite a bit to add to the WebConfigModification collection. Here OWNER, is something you set somewhere else and keep handy for when you have to remove all of the changes from the web.config.
webApp.WebConfigModifications.Add(CreateControlSection()); webApp.WebConfigModifications.Add(CreateSafeControl(webExtensionAssembly,"System.Web.UI")); webApp.WebConfigModifications.Add(CreateAjaxAssembly(webExtensionAssembly)); webApp.WebConfigModifications.Add(CreateHttpScriptHandler(scriptModuleAssembly,"ScriptModule")); webApp.WebConfigModifications.Add(CreateScriptResource(scriptResourceHandler,"ScriptResource.axd","GET,HEAD")) webApp.WebConfigModifications.Add(CreateScriptResource(webScriptAssembly,"*_AppService.axd","*")); webApp.WebConfigModifications.Add(CreateScriptResource(webScriptAssembly,"*.asmx","*")); webApp.WebConfigModifications.Add(CreateWebServerSection()); webApp.WebConfigModifications.Add(CreateWebServerHandlerSection()); webApp.WebConfigModifications.Add(RemoveWebServiceHandler(scripthandlerfactory)); webApp.WebConfigModifications.Add(RemoveWebServiceHandler(scripthandlerfactoryappservice)); webApp.WebConfigModifications.Add(RemoveWebServiceHandler(scriptresource)); webApp.WebConfigModifications.Add(CreateWebServiceHandler(webScriptAssembly,"*.asmx","*",scripthandlerfactory)); webApp.WebConfigModifications.Add(CreateWebServiceHandler(webScriptAssembly,"*_AppService.axd","*",scripthandlerfactoryappservice));webApp.WebConfigModifications.Add(CreateWebServiceHandler(scriptResourceHandler,"ScriptResource.axd", "GET,HEAD", scriptresource)); webApp.Farm.Services.GetValue().ApplyWebConfigModifications(); webApp.Update(); /* Thus begins the many methods to add each little piece of the web.config */ private SPWebConfigModification CreateScriptResource(string assembly,string path,string verb) { return new SPWebConfigModification { Path = "configuration/system.web/httpHandlers", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, Name = string.Format(CultureInfo.InvariantCulture,"add[@verb='{2}'][@path='{1}'][@type='{0}'][@validate='false']",assembly,path,verb), Owner = OWNER, Sequence = 0, Value = string.Format(" ", assembly,path,verb) }; } private SPWebConfigModification CreateWebServiceHandler(string assembly,string path,string verb,string name) { return new SPWebConfigModification { Path = "configuration/system.webServer/handlers", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, Name = string.Format(CultureInfo.InvariantCulture,"add[@verb='{2}'][@path='{1}'][@type='{0}'][@preCondition='integratedMode'][@name='{3}']",assembly,path,verb,name), Owner = OWNER, Sequence = 0, Value = string.Format(" ", assembly,path,verb,name) }; } private SPWebConfigModification RemoveWebServiceHandler(string name) { return new SPWebConfigModification { Path = "configuration/system.webServer/handlers", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, Name = string.Format(CultureInfo.InvariantCulture,"add[@name='{0}']",name), Owner = OWNER, Sequence = 0, Value = string.Format(" ",name) }; } private static SPWebConfigModification CreateHttpScriptHandler(string assembly,string name) { return new SPWebConfigModification { Path = "configuration/system.web/httpModules", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, Name = string.Format(CultureInfo.InvariantCulture, "add[@name='{0}'] [@type='{1}']",name, assembly), Owner = OWNER, Sequence = 0, Value = string.Format(" ",name, assembly) }; } private static SPWebConfigModification CreateAssembly(string assembly) { return new SPWebConfigModification { Path = "configuration/system.web/compilation/assemblies", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, Name = string.Format(CultureInfo.InvariantCulture, "add[@assembly='{0}']", assembly), Owner = OWNER, Sequence = 0, Value = string.Format(CultureInfo.InvariantCulture, " ", assembly) }; } private static SPWebConfigModification CreateAjaxAssembly(string assembly) { return new SPWebConfigModification { Path = "configuration/system.web/pages/controls", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, Name = string.Format(CultureInfo.InvariantCulture, "add[@tagPrefix='{0}'][@namespace='{1}'][@assembly='{2}']","asp","System.Web.UI", assembly), Owner = OWNER, Sequence = 0, Value = string.Format(CultureInfo.InvariantCulture, " ","asp","System.Web.UI", assembly) }; } private static SPWebConfigModification CreateSafeControl(string assembly, string nameSpace) { return new SPWebConfigModification { Path = "configuration/SharePoint/SafeControls", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode, Name = string.Format(CultureInfo.InvariantCulture, "SafeControl[@Assembly='{0}'][@Namespace='{1}'][@TypeName='*'][@Safe='True']", assembly, nameSpace), Owner = OWNER, Sequence = 0, Value = string.Format(CultureInfo.InvariantCulture, " ", assembly, nameSpace) }; } private static SPWebConfigModification CreateControlSection() { return new SPWebConfigModification { Path = "configuration/system.web/pages", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection, Name = "controls", Value =@" ", Sequence = 0, Owner = OWNER }; } private static SPWebConfigModification CreateWebServerSection() { return new SPWebConfigModification { Path = "configuration", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection, Name = "system.webServer", Value =@" ", Sequence = 0, Owner = OWNER }; } private static SPWebConfigModification CreateWebServerHandlerSection() { return new SPWebConfigModification { Path = "configuration/system.webServer", Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection, Name = "handlers", Value =@" ", Sequence = 0, Owner = OWNER }; }
So, why on earth does it take that much code to generate the xml required to use ajax in Sharepoint?
Last week while doing the usual (web development stuff) I discovered a few Firefox extensions I didn't even know I was missing until I found them by accident. The "accident" happened while adding Firebug to a Firefox that was running in a VMWare Fusion Windows virtual machine on which I was testing in, gasp, Windows. I went to find add-ons and searched for Firebug. And up came not only Firebug but also results for Firecookie, Firefinder, Inline Code Finder for Firebug, and CodeBurner for Firebug.
Of course everyone doing web development uses Firebug (or really should anyway) since it rules. But these other extensions provide some really nice functionality and complement Firebug perfectly. Here's a quick run down:
Firecookie
Firecookie lets you see all the cookies for a site, add new ones, remove existing cookies, etc. It gives useful information about each cookie like the name, value, raw value (if URI-encoded), domain, size, path, expiration, and security. Very cool.
Firefinder
Firefinder for Firebug lets you search for elements on a page using either CSS expressions or an XPath query. In the list of matching elements, you can expand each result, inspect the element by clicking the "Inspect" link, or click "FriendlyFire" which will copy the content you're looking at and post it up to JS Bin. (Be careful with this one if you have code you'd rather not have going up over the wire to a different web site.) Firefinder also puts a dashed border around each matching element it found. As you hover over search results, it highlights the matching element in the page. This is really useful when you want to find all elements matching a CSS expression or when you'd like to use XPath to find specific elements. Nice.
Inline Code Finder for Firebug
The Inline Code Finder does just that. It finds inline CSS styles, JavaScript links, and inline events, and reports the number of each of these in its results pane. Even better, it highlights each of these problems on the page you are viewing with a thick red border, and as you hover over them it shows you what the problem is in a nicely tooltip. This is really nice to help you become less obtrusive by writing more unobtrusive JavaScript and avoiding inline styles. For older sites or sites that weren't designed with "unobtrusivity" in mind though, be warned that there might be a lot of red on the page!
CodeBurner for Firebug
CodeBurner for Firebug provides an inline HTML and CSS reference within Firebug. It allows you to search for HTML elements or CSS styles and shows a definition and an example. It also provides links to the awesome Sitepoint reference and even to the Sitepoint live demos of the feature you are learning about. This is so unbelievably useful to have a HTML and CSS references directly within Firebug it isn't even funny. Thanks Sitepoint.


