If you have done any decent amount of work with the ASP.NET MVC platform, you have probably run into the following problem. You have a page where you want to update data on the server without a postback and so you whip out some fancy Javascript to send a request to the server. What happens is the response you get back is a success, and the data is updated, but subsequent requests don’t seem to be updated. This is most noticeable with partial views and content views called via the infamous “$.ajax” call. What you forgot was to make sure the browser isn’t caching the result:
1 | HttpContext.Response.AddHeader("cache-control", "no-cache"); |
Note that if you have already hit the particular view and it is cached, you can generally clear the cache by navigating to the URI of the view manually and hitting refresh.
A common problem for beginning ASP.NET developers is relative linking to CSS files in a MasterPage file. As it turns out, this is incredibly easy as shown below. Even better is that it works in ASP.NET MVC!
1 | <link rel="Stylesheet" href="<%= ResolveUrl("css/Master.css") %>" type="text/css" media="screen" /> |
After developing with the Sitecore CMS for a couple of months I have seen what XSLT can offer in terms of a powerful web technology. I decided early on, before using Sitecore, that Vodka 2.0 would have to support XSL transforms since the content is stored as XML. The following is a sample of how to work with XML and XSLT in the second version of the Focused Games Framework (FGF 2.0).
While the XSLT code can go pretty much anywhere in the ASP.NET pipeline, for now I have put it in my main Controller. Note that this code is not final, I will be looking into a better way to streamline the content retrieval process.
1 2 3 4 5 6 | public class ContentController : Controller { public ActionResult Get(string uri) { Content content = GetContent(uri, -1); Content template = GetContent(content.TemplateId, -1); |
Next the XslTransformer class is instantiated and a test extension is added. Extensions can be simple or complext .NET classes. Again I plan to streamline this process and support loading from the web.config file.
1 2 3 4 5 6 7 8 9 10 11 12 13 | XslTransformer transformer = new XslTransformer(GetDocument); transformer.AddExtension( new XsltExtension { Namespace = "http://focusedgames.com/vodka", Provider = new VodkaXslExtensions() } ); ViewData["Content"] = transformer.Transform(uri, template.Meta.Uri); return View("Get", "~/Themes/FGDN/Theme.master"); } |
When the Transform method is invoked, the transformer attempts to load documents through a callback. This process will definitely be streamlined so that the re-implementation of the following method isn’t required. The callback method loads the content straight from the database through an SqlContentProvider object. Not much has really changed here since Vodka 1.0 except for the addition of support for both languages and versioning.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public Content GetContent(string uri, int parent) { SqlContentProvider scp = new SqlContentProvider(); NameValueCollection parameters = new NameValueCollection(); parameters.Add(SqlContentProvider.ConnectionStringParameterName, connectionString); scp.Initialize(parameters); Content content = scp.GetContent(uri.ToLower()); return content; } private XPathDocument GetDocument(Uri uri) { Content content = GetContent(uri.OriginalString, -1); XPathDocument document = new XPathDocument(new StringReader(content.Xml)); return document; } } |
And finally the simple extension object:
1 2 3 4 5 6 7 | public class VodkaXslExtensions { public string GetDate() { return DateTime.Now.ToString(); } } |
So what does this produce exactly? Well it takes the following XML…
1 2 3 4 5 6 7 8 9 | <?xml version="1.0"?>
<content>
<title>Home</title>
<description>
<p>This website is still under construction, please check back soon.</p>
<p>Thank you,</p>
<p><a href="http://jsedlak.com">John Sedlak</a></p>
</description>
</content> |
And uses the following XSLT file (stored in the Vodka Database)…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http://focusedgames.com/vodka" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl test"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<h2>
<xsl:value-of select="title"/>
</h2>
<div class="Description">
<xsl:value-of select="description"/>
</div>
<p><xsl:value-of select="test:GetDate()"/></p>
</xsl:template>
</xsl:stylesheet> |
And produces the following HTML…
1 2 3 | <h2>Home</h2> <div class="Description">This website is still under construction, please check back soon.Thank you,John Sedlak</div> <p>9/21/2009 5:23:04 PM</p> |
Scott “Gu” (Guthrie) has started a series of posts about VS2010 and (more importantly) .NET 4.0, touting its new features that so far have been incredibly important for developers. It seems that Microsoft is finally “getting it” and listening to us about certain things.
While most of you have already heard about the ability to define Debug and Release web.config files, these two new features may put you over the edge in waiting for .NET 4.0 to release.
Finally Microsoft has realized that while having configuration files that are verbose enough to support wild customizations, most of us do not need to change the default sections in the web.config file. So it should come as no surprise that clean configuration files will now be a thing of the (recent) past. It is just a shame it took so long to get.
Hidden in this post about new project templates and what looks to be the ASP.NET WebForms version of the ASP.NET MVC template is a bit about client ids for controls.
All of the styles and content within the site are configured using CSS, and take advantage of some of the new features with Web Forms in ASP.NET 4 – including clean client-side “id” names (no more ctrl_ mangled names – ASP.NET 4 gives you complete control over the client id), and CSS based rendering instead of table based rendering for the built-in server controls.
This, again, should come as no surprise as the mangled names can present problems for developers looking to write some quick javascript as well as those looking to simply clean up their HTML. Here’s to hoping that Microsoft cleans up its HTML in other places as well (SharePoint anyone?).
Pro-tip for today: When attempting to create a website (I am using ASP.NET MVC 1.0) with IIS7 that allows anonymous users under an Active Directory domain it is imperative that you remember to give anonymous users read rights to the web directory on the system’s physical file system. Otherwise you could end up with pages that do not load the CSS correctly.
Furthermore, if you are running into assembly load problems when running on Windows Server 2008 R2 remember that everything is running in X64 and that you need to enable 32-bit compatibility in your Application Pools. To do this select the App Pool and click “Advanced Settings” and set “Enable 32-Bit Applications” to true.
Here is a quick and incredibly useful tip for using the Sitecore API. Recently I was looking for an easy way to strip HTML tags from a string (in C# code) and Alex de Groot responded to the call. Turns out that the process is insanely painless.
1 | Sitecore.StringUtil.RemoveTags(string) : string |
One of the major gripes I have with the Windows operating system is its inability to build decent event logs when an exception occurs. This is particularly annoying on the server builds because as a developer, I need to know what is causing a crash or a hang. Recently I have been developing a site using Sitecore and after a publish the site started crashing and bringing down the entire server. The following is an overview of how I solved the issue.
The first thing I did was check the Event Viewer on the server itself – notice the horrible information within the error. The one important code to write down is the exception code (0xE053534F).
After reading a tutorial on how to catch a crash I was able to catch the crash in a dump file. While the debug diag tool was useful for catching, I needed WinDbg to get to the root of the problem.
Note: I set the symbols location to SRV*c:\users\jsedlak\documents\websymbols*http://msdl.microsoft.com/download/symbols
As you can see, the debug view is fairly useless. Run the following commands:
Now you can see what is causing the stack overflow. Turns out it was an XSLT file that was doing a recursive climb up the Sitecore tree without a base case. The cause of the problem however was that I had just implemented Workflow on all items which corrupted their state and seemed to have removed their published version from the web database. By fixing the XSLT to have a base case and submitting all content through their workflow I was able to get the site back.
One of the major design decisions for Vodka 2.0 has been how to handle the installation of all the software necessary to run a site. At first I favored a desktop application based install since it would allow me to write in normal .NET code without any problems or hurdles that the web presents. The problem with this idea is that a desktop based install isn’t feasible for most people, certainly not for those on shared hosting.
A client application based installation is what I call an Exploding Installation because it takes a package and pushes files out of it onto the file system. Thus it is exploding itself onto the computer. This works really well for most cases, especially basic software installs like games, office applications, et cetera.
Where such an explosion doesn’t work well is for web based installations, which is where Vodka 2.0 is headed (see screenshot below). This is due to the fact that in most cases the average user isn’t able to set up the server in a way to make it work, or doesn’t want to. Originally the installation procedure was going to be based on an explosion: the user would upload the files, put in the site information (see screenshot below) and then the installation would unpackage the files necessary to run the site based on the information. This would work very well, except it leaves the original install files at the root directory of the server. Instead of this approach, an Imploding Installation does the trick because it not only erases over the install files themselves (big security bonus), it doesn’t require any work to setup. The goal here is to have the user upload the files, run the install and get to work creating content.
So how is this done? To support an implosion of the software, or rather a rewrite of key points of it the software needs to be modular in such a way that programmatic writes can be done over content areas. In the case of the Vodka install the site’s navigation needs to be rewritten and because it is based on ASP.NET MVC has to handle the shutdown and/or removal of the installation controller and views. Right now this is done by removing a simple text file from the server, although in the future it can be done by changing a portion of the web.config file and/or removing an extra “Install” library from the bin directory.
The best part about the implosion is that it is 100% clean. After an installation is completed, there is no evidence left that it ever took place, and no possible way for a user to rerun the installation.
Tackling the problem in the previous post I have decided to rely on providing more options than necessary. I have to remember that because Vodka is not client software, I have to write it as if the client software will be as simple as possible. The goal of Vodka is to give developers a way of setting up a software based CMS with great ease.
To do this, I have built in services that can be implemented and exposed via WCF as well as built in implementations of these services. If you had the binaries for Vodka, you could reference FocusedGames.Vodka.Services, create a class in a Service project and inherit from ContentService or MembershipService. After deploying the project, you can treat it like any other WCF service reference.
The original question dealt with translation services however, is it a client or server responsibility? You would generally make it client side because you may wish to get a different template for the content or change how translation is done. This is on par with most CMS software installs out there but there is a problem. Templates in the Vodka backend are treated as standard items of content. It then would require two calls to the service: one for the template and one for the content. You would also have to know how the template is extracted from the content item. This is a bad idea as it increases server load unecessarily.
The answer is simple: abstract it and keep it server side. The idea here is that the developers can plugin their own template provider into the service when setting it up. This will allow them to point to another service, a local directory or hardcoded templates. If no plugin is used, the service will continue on its standard course, grabbing the template from the standard content data store.
You may be asking why you would ever want to use a custom provider to point to a second service. Let’s say you have a ton of websites that you all want to look the same. For instance Microsoft may have microsoft.com, msdn.microsoft.com, creators.xna.com, xbox.com, et cetera and may want them to all use the same templates for items. They could use a provider to point to a single template service removing the need to change 5+ templates on 5+ servers.