I like to explore interesting new technologies. I also love to learn more from the materials available on Microsoft Virtual Academy, Google Developers channel, and several other tech/dev events.
PRG stands for Post-Redirect-Get, a web development design pattern which targets to avoid duplicate form submissions because of refreshing the web page.
Currently, in most of the modern browsers, when we refresh the web page right after we submit a form in the page, we will receive a confirmation alert box asking if we confirm want to re-submit the same form.
The warning received when pressing F5 right after submitting a form on the page.
This can happen in an e-commerce website. If the customer accidentally pressed “Continue” button on the box to proceed, then there may be a duplicate online purchase. The confirmation box is good but it does not remove the risk of form re-submission.
To avoid all these issues, PRG web design pattern is introduced.
PRG design pattern can solve the problem of form re-submission. (Image Credit: Wikipedia)
PRG and ASP .NET Web Form
In ASP .NET Web Form context, instead of returning a web page direct, we will do a Response.Redirect (302 Redirect) to a confirmation page (or redirect back to the original same page) first. So now user can safely refresh the result page without causing the form re-submission.
By using PRG design pattern, we will thus need to store the data somewhere so that the two web pages can communicate. For example, if we want to show the Receipt Order Number generated after the POST in the confirmation page, then we can store the number in Session variable.
PRG and ASP .NET MVC
In ASP .NET MVC, instead of using Response.Redirect, we will be using RedirectToAction. Then we will store the data in TempData for the next page to consume, for example.
Thoughts about PRG
PRG design patter is not good for every case having form submission involved. For example, if we have a report module that user can search by providing start date and end date, then it is fine to have form re-submission with every page refresh.
Razor is still a new markup language to me, after working on ASP .NET Web Form projects for 3 years. I started to learn Razor in the beginning of this year (2015), so I decide to note down what I find interesting in my Razor learning journey and then share it here.
A Powerful HTML Helper Method: EditorFor
When I first started learning Razor, I was confused by EditorFor and TextboxFor. So, what is the difference between both of them?
TextboxFor is easy to understand. It is a helper method is used to render a TextBox on the web page no matter which type of the data is passed to the method.
Even though the datatype is specified to be DateTime, EditorFor does not provide a control for time section.
EditorFor Accepts Custom Templates
By default, the EditorFor will create a textbox with calendar popup for data which is DateTime. We can change it to use another look-and-feel by create our own template.
So let’s say we want the EditorFor to render five dropdown boxes for each of the following components in DateTime: Year, Month, Day, Hour, and Minute.
@model MyProject.Models.DropDownDateTime
@{
List<SelectListItem> years = new List<SelectListItem>();
int prevYearCount = Model.PreviousYearCount;
int nextYearCount = Model.NextYearCount;
for (int i = Model.DateTime.Year - prevYearCount; i <= Model.DateTime.Year + nextYearCount; i++)
{
years.Add(new SelectListItem() {
Text = i.ToString(),
Value = i.ToString(),
Selected = (i == Model.DateTime.Year ? true : false) });
}
List<SelectListItem> months = new List<SelectListItem>();
for (int i = 1; i <= 12; i++)
{
months.Add(new SelectListItem() {
Text = i.ToString("00"),
Value = i.ToString(),
Selected = (i == Model.DateTime.Month ? true : false) });
}
List<SelectListItem> days = new List<SelectListItem>();
for (int i = 1; i <= 31; i++)
{
days.Add(new SelectListItem() {
Text = i.ToString("00"),
Value = i.ToString(),
Selected = (i == Model.DateTime.Day ? true : false) });
}
List<SelectListItem> hours = new List<SelectListItem>();
for (int i = 0; i < 24; i++)
{
hours.Add(new SelectListItem() {
Text = i.ToString("00"),
Value = i.ToString(),
Selected = (i == Model.DateTime.Hour ? true : false) });
}
List<SelectListItem> minutes = new List<SelectListItem>();
for (int i = 0; i < 60; i += 15)
{
minutes.Add(new SelectListItem() {
Text = i.ToString("00"),
Value = i.ToString(),
Selected = (i == Model.DateTime.Minute ? true : false) });
}
}
@Html.DropDownList("years", years)
@Html.DropDownList("months", months)
@Html.DropDownList("days", days) at
@Html.DropDownList("hours", hours) :
@Html.DropDownList("minutes", minutes)
So, with the help of this template, whenever I pass in a data which has DropDownDateTime as its type, EditorFor will automatically render the five dropdown lists, as shown in the screenshot below.
Yup, customized look-and-feel for DateTime picker.
Razor and Content
When I am building apps using ASP .NET Web Forms, I often need to add some server codes within the HTML in .aspx file. For example,
In Razor, we do not need to explicitly denote the start and end of the server blocks within our HTML. The Razor parser is smart enough to implicitly identify when a server block ends by looking for HTML tags. Hence, Razor is able to keep the HTML clean, as shown in the sample coe below.
However, there are sometimes where the Razor parser cannot do the job properly, especially when we need to mix Razor and Javascript code. For example, when we are rendering diagram using Google Charts, as shown in the sample below.
@{ int counter = 0; }
var data = new google.visualization.DataTable();
data.addColumn('string', 'Sales Date');
data.addColumn('number', 'Sales');
data.addRows([
@foreach (var record in dailySalesSummaryRecords)
{
counter++;
if (counter == dailySalesSummaryRecords.Count())
{
@:['@record.Key', @record.TotalSales.ToString("0.00")]
}
else
{
@:['@record.Key', @record.TotalSales.ToString("0.00")],
}
}]
);
...
The @: Character Sequence is used to explicitly tell Razor to interpret the following line of content as content. However, @: can only work on single line. So for scenarios with multiple lines of content, we need to do something as follows.
...
@: Line one of content
@: Line two of content
@: Line three of content
...
Alternatively, we can just use <text> Tag to effectively mark the start and end of content.
...
<text>
Line one of content
Line two of content
Line three of content
</text>
...
<text>
{
title: '@Html.Raw(HttpUtility.JavaScriptStringEncode(s.Name))'
start: new Date(@s.Starts.Year, @s.Starts.Month-1, @s.Starts.Day),
end: new Date(@s.Ends.Year, @s.Ends.Month-1, @s.Ends.Day)
}
</text>
Wait… We don’t want apostrophes to be encoded as ‘ in the first place? Why do we doing encoding now?
This is because JavaScriptStringEncode, a newly introduced method in .NET 4, will encode apostrophes not as ' which is something not human-friendly, but it will encode it as \’. So yup, this solve the problem.
JavaScriptStringEncode is a great feature which helps us to handle encoding C# string to a JavaScript string. It is able to escape not only apostrophes, but also double quotes (“), question marks (?), backslash (\), and ampersand (&).
It has been about half a year since I started to learn ASP .NET MVC and Entity Framework (EF). In this period of time, I have learnt about not just MVC and EF, but also Azure PaaS, Google Maps API, web application security, cool jQuery plugins, Visual Studio Online, etc.
In the beginning of May, I started to note down useful things I’d learned in my learning journey. Months of bringing together information in this summer has helped me compile my notes about what I’ve learned in the past 6 months. I have currently completed compiling notes for 17 topics that I’ve learnt in this summer.
I listed down the title of the 17 posts below to give you a quick overview about all the 17 topics.
I’m working in Changi Airport. The office working hour is from 8:30am to 6pm. In addition, I am staying quite far from the airport which will take about one hour for me to travel from home to office. Hence, the only time that I can have sufficient time to work on personal projects is weekends.
This summer self-learning project is originally planned to be done by the end of May. Normally, it takes me about one day to finish writing a post. After that, if I find any new materials about the topics, I will then modify the post again. Sometimes, however, I am just too tired and I would not write anything even though it’s weekend. Hence, I end up finishing all the 17 topics three months later.
This summer learning project covers not only what I’ve learnt in my personal projects, but also new skills that I learn in my workplace. I always enjoy having a chat with my colleagues about the new .NET technology, app development, Azure hosting, and other interesting development tools. So yup, these 17 articles combine all the new knowledge I acquire.
I’m also very happy that that I am able to meet developers from both .NET Developers Community Singapore and Azure Community Singapore and share with them what I’ve learnt. That gives me a great opportunity to learn from those experienced .NET developers. =)
Azure Community March Meetup in Microsoft Singapore office.
I am not that hardworking to work on personal projects every day. Sometimes, I will visit family and friends. Sometimes, I will travel with friends to overseas. Sometimes, I will play computer games or simply just sleep at home. So ya, this self-learning project takes a longer time to complete. =D
Working on personal projects after work is stressful also. Yup, so here is a music that helps reducing my stress. =)
Since Visual Studio 2012, we can always find this file called modernizr-(version).js in the default ASP .NET 4.5 MVC template. So, what is Modernizr (can be downloaded from Nuget)?
With this information, we will then be able to provide alternative look-and-feel for those users who are using older versions of browser instead of telling those users “Best view in version xxx of browser yyy”.
With YepNope.js, we will also be able to tell Modernizr what to test and then what JS/CSS to load if the test passes or fails.
Finally, please remember that Modernizr only provides us information about which features are (not) supported. It won’t magically enable those features for us. We need to write corresponding JS/CSS to provide alternative views when the features are not supported on the browser.
In short, Modernizr is a good tool for designers to implement the idea of Progressive Enhancement.
The famous border-radius feature in CSS3 is supported in modern browsers like IE11, Edge, Chrome, and Firefox but it’s not supported in Internet Explorer 7 and 8. Does this stop us from using border-radius in our website? Nope. This is because for users who are still using IE7/8, they can still use the website in the same way as those who are using modern browsers. Just that those who are using old browsers cannot see the beautiful effect of border-radius.