If you are like me you might have developed lots of web applications using different versions of the ASP.NET MVC framework, and might wonder how the latest installations may affect the ability to run.
When upgrading to the latest Release Candidate 2 these old projects will probably build just fine, but there will most likely be some kind of run time error when running locally, like the one I just got and showing below.
Why the breakage you might wonder and remembering that you been putting those old versions in your bin-folder and they should not be affected. Dylan Bettie gives us the explanation:
The CLR checks the GAC first when resolving assembly references - and if it finds a matching assembly in the GAC, it won't look anywhere else. The ASP.NET MVC previews and beta release all use the same assembly version, culture and public keys, so the CLR has no way of distinguishing between the preview 3 version of System.Web.Mvc and the beta version of the same assembly. They're different DLLs with different file versions, but because the assembly version is the same, the CLR regards them as the same assembly.
So what you need to do is to remove the ASP.NET MVC assemblies from your GAC and your old projects will run against the old ones in their bin.
Luckily I've done this before from the instructions in Dylans post and it's not that hard. Just make sure you backup your system before you do anything because it involves editing the registry which you knows is not always safe. For my safety I have just made a snapshot of my Windows 7 system I got running in WMware Fusion.
Remove the assembly from the registry
Firstly you need to run regedit and find HKEY_CLASSES_ROOT\Installer\Assemblies\Global and remove the key System.Web.Mvc,version="1.0.0.0",culture="neutral", publicKeyToken="31BF3856AD364E35",processorArchitecture="MSIL"-key
Un-GAC it
Fire up a CMD prompt and locate your Gacutil.exe. On my Windows 7 system running team edition of Visual Studio 2008 it can be found here. C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin. Then run the command gacutil /u System.Web.Mvc
Test your projects
Your old projects made with the previews or betas should now run just fine as they will use the ddl:s you got in their respective bin folder. Mine is running fine as you can see.
TinyMCE is a nice HTML-Editor which has become very popular. It's easy to use and has a lot of configuration possibillities. But when it come to combining it to Ajax and partial updates - it can be a nightmare...
I have now done a proper test and will provide the source code for anybody who is interested, free of use in any way. I've tested this code successfully in IE7, FF2 and Opera.
But now let the source speak for it self, don't miss out on the complete project download at the bottom.
Default.aspx
<%@ Page Language="C#" ValidateRequest="false" Trace="false" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>MS Ajax UpdatePanel - TinyMCE</title> <script type="text/javascript"> function SaveMyPreciousValues() { tinyMCE.triggerSave(false,true); TextBox1 = document.getElementById('TextBox1'); alert('Check value when posting: '+ TextBox1.value) } </script> </head> <body>
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if(!Page.IsPostBack) LoadTinyMCE(); }
private void LoadTinyMCE() {
//Load tinyMCE HtmlGenericControl Include = new HtmlGenericControl("script"); Include.Attributes.Add("type", "text/javascript"); Include.Attributes.Add("src", "js/tiny_mce/tiny_mce.js"); this.Page.Header.Controls.Add(Include);
Label1.Text = "Content posted from TextBox1: " + inputText;
//Register some javascript to redraw the editor. //Very important to reset the id-counter to "0", or else strange things will happen.. ScriptManager.RegisterClientScriptBlock(UpdatePanel1, this.GetType(), "init", "tinyMCE.idCounter=0;tinyMCE.execCommand('mceAddControl', false, 'TextBox1');", true); } }
On the web site you can use The Code Wiki to explore it's own source code which is really cool. It's also possible to give comments on each resource in the project.
I really love developing on ASP.NET with C# and will definitely continue using this technique from Microsoft. But everything can not be perfect. The greatest shortcoming of the framework is to me that there isn't any good native support for URL-rewriting. I have written a bit about it before.
It's especially in the IIS 6 web server that the limitations exists. In the newer IIS 7 that will be released together with the Longhorn server there will be better solutions to create rules for URL rewrites. But there are some time left until this system will be released, so that doesn't help us right now.
What you can do at the moment is to use ASAPI-filters but that postulates that you are running your own dedicated server or are on a web host that will install it for you. Jeff Atwood at Coding Horror writes more about the two most common ASAPI-solutions for IIS.
One of the greatest critics of the situation is probably Mike Schinkel. This is the guy that started the wiki.welldesignedurls.org and the companion blog which contains a lot of great resources on the subject.
On his personal blog Mike is not holding back on the critizism. In a recent post with the headline "IIS 7.0: Too Little, Too Late?"another Mike (Program Manager för Microsofts IIS team) enters the discussion and is expressing his regrets over the bad situation.
I think it's really good that a lot of developers pays attention to the problem. Microsoft tells us that IIS 7 will not be available for Windows 2003 and that's a real pity. The new techniques are to deep related to the Longhorn system that are saying.
But who knows, after all this begging from developers perhaps Microsoft can spare some resources on it. I would be absolutely wonderful. My tip is to try to do a simpler upgrade to IIS 6 and try to make an implementation of the same URL-rewrite as in the upcoming web server. Name it something like IIS 6.5.
Some time ago I wrote about how to do URL rewrite with ASP.NET (and about the problems that are involved). Many developers has tried to tackle the problem and I will not go to ddep into the technical stuff this time. I will how ever save a few new links I found on the subject.
My conclusion is that it's probably smartest to wait until IIS 7 is released. Unfortunatly it doen't seems like we will get this web server for Windows 2003. We will probably have to wait for the new Longhorn server.
IIS 7.0 will have much better support for URL-rewrite as you can read on Scott Guthrie's blog:
Several people have asked why the built-in URL Mapper in ASP.NET 2.0 doesn't support regular expressions. There were actually a few reasons for this -- one of the big ones being that just about the time we were about to consider adding it my team started also working on IIS7. We realized that a full-featured version would want/need to take advantage of some of the new features in IIS7 as well as the support all content types (in particular -- images and directories). So we postponed making it feature rich until a future version.
The question is if one really can wait. To have nicely formatted URLs is really tempting, especially from an SEO-perspective. But if you are going to use one of this tecniques just bear in mind that you might have to redo everything once IIS 7 is released.
If you want to have some thought from someone who has started using URL-rewrite with IIS 7 on Vista, you can read Dennis blog.
This is an example of a class that generates passwords. I have used it for so long that i forgot where I found it originally. If you recognize the code, please let me know the origin and I will add a reference.
using System; using System.Data; using System.Configuration; using System.Web; using System.Text; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; /// /// Summary description for PasswordGenerator /// public class PasswordGenerator : Page { private char[] characterArray; private Int32 passwordLength = 10; Random randNum = new Random(); public PasswordGenerator() { characterArray = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray(); } private char GetRandomCharacter() { return this.characterArray[(int)((this.characterArray.GetUpperBound(0) + 1) * randNum.NextDouble())]; } public string Generate() { StringBuilder sb = new StringBuilder(); sb.Capacity = passwordLength; for (int count = 0; count <= passwordLength - 1; count++) { sb.Append(GetRandomCharacter()); } if ((sb != null)) { return sb.ToString(); } return string.Empty; } }
This is an error which is caused by posting html-code in a textbox. The text doesn't need to contain valid HTML, just anything with opening and closing angled brackets ("<...>").
The complete error:
Description: Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted. This value may indicate an attempt to compromise the security of your application, such as a cross-site scripting attack. You can disable request validation by setting validateRequest=false in the Page directive or in the configuration section. However, it is strongly recommended that your application explicitly check all inputs in this case.
Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client (ctl00$mainContentPH$fvFaq$tbFaqBody_sv-SE="...the link <a href="http://www....").
Solution There are two ways to disable request validation.
A warning for injection The validation is there for a reason. If you turn it off, visitors can post code like this, and that's not wanted in most cases.
string ColumnName = null; //error will be thrown if the variabe ColumnName is null if(ColumnName ==null) ColumnName=string.Empty; SqlParameter param = new SqlParameter("@ColumnName", SqlDbType.NVarChar, 100); param.Value = ColumnName; cmd.Parameters.Add(param); cmd.Execute();
Update: The web service used in this example is not availible any more.
I was inspired by an article about currency conversion on Code Project when I made my own example. Please read the article in the link below to find out how to add an Web Service to your project. I am using a Web Service from xmethods.net.
//Fysisk sökväg på servern (Byt ut mot den på din server) string strXMLPath = "C:/ . . . /rss.xml";
FileStream objFileStream = new FileStream(strXMLPath,FileMode.Create); XmlTextWriter xtw = new XmlTextWriter(objFileStream,System.Text.Encoding.GetEncoding("iso-8859-1")); xtw.Formatting = Formatting.Indented; xtw.WriteStartDocument();
//skriv ut <rss version="2.0"> xtw.WriteStartElement("rss"); xtw.WriteAttributeString("version","2.0");
//skriv ut <channel> xtw.WriteStartElement("channel");
//skriv ut element som tillhör <channel> xtw.WriteElementString("title","Codeodyssey.se"); xtw.WriteElementString("link","http://www.codeodyssey.se/"); xtw.WriteElementString("description","Code Odyssey - expanderar webben"); xtw.WriteElementString("language","sv-SE"); xtw.WriteElementString("copyright","Copyright (c) 2004-2006 Code Odyssey");
OleDbConnection conn = new OleDbConnection (strConn); bool boolPermission = false; OleDbDataReader objDataReader=null; try { string strSQL = "SELECT Blog.Id, Blog.Title, Blog.Body, Blog.PublishDate FROM Blog ORDER BY Blog.PublishDate DESC";
conn.Open();
OleDbCommand objCommand = new OleDbCommand(strSQL, conn); objDataReader = objCommand.ExecuteReader(); while (objDataReader.Read() == true) { int Id = Convert.ToInt32(objDataReader["Id"]); string Title = Convert.ToString(objDataReader["Title"]); string Body= Convert.ToString(objDataReader["Body"]); //Se till att datum följer RFC-822 standard string PublishDate = Convert.ToString( ((DateTime)objDataReader["PublishDate"]).ToString("r"));
This is how to add such a link from the code behind:
//Add RSS link HtmlLink link = new HtmlLink(); link.Attributes.Add("type", "application/rss+xml"); link.Attributes.Add("rel", "alternate"); link.Attributes.Add("href", "feed/rss.xml"); this.Page.Header.Controls.Add(link);