Archive for August 2010
18
HTML Unencoding for Razor View Engine on ASP.Net MVC 3 Preview 1
2 Comments · Posted by A.K. in Blog, Software
I have been using the Razor engine for a few days now, and I am liking it a lot. I noticed one big problem right from the start, all strings are HTML encoded. For our uses, this becomes quite an annoying “feature” when we deal with JSON strings. For example, given a simple JSON string,
The actual HTML encoded output of this became,
The quotes have been escaped, which is not the desired output. If we need to send HTML back out, or XML, we would have to then individually escape those. Overall, I find this quite annoying as we would have to wrap it inside of an HtmlString as shown in this StackOverflow post.
In our scenario, we are generating JSON/XML from C#, so most of the time, our serialized data is inside of the ViewModel. Which would result in us doing things like,
@(new HtmlString(View.Bar))
As you can see, this can become quite cumbersome. So I decided to plagiarized part of MVC to create a RawView. In the end, the usage will be,
@RawView.Bar
I also went ahead to allow the usage of the index operator as well in case there’s a need to loop over it with a list of keys.
@{
List keys = new List { "Foo", "Bar", "Baz" };
foreach (var key in keys) {
@RawView[key]
}
}
To achieve this, I would need to duplicate DynamicViewDataDictionary. Naturally, I named it DynamicRawViewDataDictionary,
{
private readonly Func viewThunk;
public DynamicRawViewDataDictionary(Func viewThunk)
{
this.viewThunk = viewThunk;
}
private ViewDataDictionary ViewData
{
get
{
ViewDataDictionary viewData = this.viewThunk();
return viewData;
}
}
public object this[string key]
{
set { setData(key, value); }
get { return getData(key); }
}
public override IEnumerable GetDynamicMemberNames()
{
return ViewData.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = getData(binder.Name);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
setData(binder.Name, value);
return true;
}
private object getData(string key)
{
object value = ViewData[key];
if (value is string)
{
return new HtmlString(value.ToString());
}
return value;
}
private void setData(string key, object value)
{
ViewData[key] = value;
}
}
The reason for the duplication is because the DynamicViewDataDictionary is an internal sealed class. There was no way I could get around this restriction other than copying and pasting. The obvious change I made to this class is the getData method. I checked to see if the object is a string, if it is, I wrapped it with an HtmlString().
Now I need to use this inside of a WebViewPage, since all views , I have to have a customized version of a WebViewPage as well. Good thing that MS didn’t make this class internal sealed, so I can easily inherit from it. I needed to make a generic and a non-generic version, I just plopped both of this inside of one file.
{
private DynamicRawViewDataDictionary _rawData;
public dynamic RawView
{
get
{
if (_rawData == null)
{
_rawData = new DynamicRawViewDataDictionary(() => ViewData);
}
return _rawData;
}
}
}
public abstract class CustomWebViewPage : WebViewPage
{
private DynamicRawViewDataDictionary _rawData;
public dynamic RawView
{
get
{
if (_rawData == null)
{
_rawData = new DynamicRawViewDataDictionary(() => ViewData);
}
return _rawData;
}
}
}
For the final touch to actually make this work, at the top of the cshtml file, you should have something like,
//or
@inherits Namespace.To.CustomWebViewPage
Now that the cshtml file inherits from the new CustomWebViewPage, it should have access to RawView, which will wrap all strings with an HtmlString.
Eduardo commented below that there’s a much easier way to achieve this. By modifying /View/Web.config file and set the following should result in the same desired effect,
Once you have this in place, you’ll still need to make sure that all of your new views inherits from CustomWebViewPage. I highly recommend using custom code templates in your MVC project to generate the view. This will help with automating a lot of the mundane tasks.
asp.net mvc 3 razor view engine · html encoded · html encoded strings · razor engine html encoded · razor view engine
4
Migrating project from ASP.NET MVC 2.0 to 3.0 Preview 1
No comments · Posted by A.K. in Software, Web Development
I just downloaded ASP.NET MVC 3.0 to test out the new Razor view engine. The problem is that the previous project created in MVC 2.0 needed to be changed as well. This step is nearly identical to the process in migrating from 1.0 to 2.0. The following content is blatant plagiarism with a few details modified,
To manually upgrade an existing ASP.NET MVC 1.0 application to version 2, follow these steps:
- Make a backup of the existing project.
- In a text editor, open the project file (the file with the .csproj or .vbproj file extension) and find the ProjectTypeGuid element. As the value of that element, replace the GUID {F85E285D-A4E0-4152-9332-AB1D724D3325} with {E53F8FEA-EAE0-44A6-8774-FFD645390401}. When you are done, the value of that element should be as follows:
{E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
- In the Web application root folder, edit the Web.config file. Search for System.Web.Mvc, Version=2.0.0.0 and replace all instances with System.Web.Mvc, Version=3.0.0.0.
- Repeat the previous step for the Web.config file located in the Views folder. (Additional note: There are 4 places that you need to change to 3.0.0.0 in this file.)
- Open the project using Visual Studio, and in Solution Explorer, expand the References node. Delete the reference to System.Web.Mvc (which points to the version 1.0 assembly). Add a reference to System.Web.Mvc (v3.0.0.0).
- Add the following bindingRedirect element to the Web.config file in the application root under the configuraton section:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>(Additional note: I just replaced this entire section in my old Web.Config. Unless you have other elements, I would recommend doing the same thing.)
- Create a new empty ASP.NET MVC 2 application. Copy the files from the Scripts folder of the new application into the Scripts folder of the existing application.
- Update the existing application’s CSS file with the CSS style definitions in the Site.css file.
- Good luck!
For those unaware, I was part of a team that failed to deliver a piece of software on time. This is part of a series, which I started with this post with a little overview of what happened and my take on the entire fiasco.
When I entered the company, I had no real prior development experience. Sure, I had side projects during school here and there, but nothing I would consider to be real serious work. I had never really worked with a revision control software and I had never even touched an IDE before. It was quite a learning experience for me in the first few weeks, that is, learning about the tools and how to use them properly. A few weeks in, I had learned quite a few new things from my lead and ultimately placed all my trust in him. After all, he had over twenty years of experience, why shouldn’t I?
Those were my famous last words for the project, because I shouldn’t have. There were a lot of bad signs, and I should have noticed them earlier. My lead’s beliefs regarding on how to run a team was, dare I say, a little bit off from what I would consider industry practice. We did not have any code reviews because “we had no time.” We didn’t have milestones or deadline for deliveries because it’s an “engineering effort.” We didn’t have a clear requirement specification because a PowerPoint presentation was enough to define the software’s end result.
Looking back, I would consider the leadership to be inadequate and inexperienced. Don’t get me wrong, I did learn a lot from him. I learned what not to do if I ever lead a team.
In many conversations with him, he had explained to me the “three pillars” of software development. Quality, time, and functionality. All three are delicately balanced and intricately connected so that you cannot adjust one without affecting one of the other two. Higher quality means more time, less time means less functionality, so on and so forth. I completely agree with him, though, I would say that we disagree on is the execution of this theory.
He would constantly argue that we should ship software quickly, but we never actually cut down on any requested features. We were pushed to 80 hours / week, our productivity aggressively declined, we did not ship the software. There was too much to do, quality requirements were way too high, and there were too many features. Most of us developers know that pushing hours does not necessarily make software development any faster. We experienced that first hand.
We had atrocious bugs. Some would cause IIS to crash, others would cause the browsers to crash. On top of these, we had hundreds of less serious bugs. The problem of course, was we had no time to fix them. On the last push that I did before the “launch”, in a stretch of 16 hours, I fixed 30 bugs. I’m sure I introduced several more to the system, but gosh, that’s a lot of changes to a system to be launching. Of course, it isn’t as bad as it sounds because we had unit tests right? That’s where we went wrong again.
We had no automated tests. Need I say more?
We started to have so many bugs that it was out of any one person’s control. This avalanche of bugs kept us chasing our own tail. At one point, you would expect someone to say “enough.” Nobody did for another two months!
Now, what did I learn? A lot. Review code, write tests, voice concerns, work less, cut features, ship product, make money. We did none of that.
No tags
