- 2XX - Request worked
- 3XX - Resource moved
- 4xx - Client error
- 5xx - Server error
Sunday, July 21, 2013
HTTP Respons Status Codes
Saturday, July 20, 2013
Using KnownType in Serialization
[DataContract]
[KnownType(typeof(Student))]
[KnownType(typeof(Teacher))]
public class Person
{
[DataMember]
public string Name{get; set;}
}
//Serialize all derived types of Person.
[DataContract]
[KnownType("GetDerivedTypes")]
public class Person
{
[DataMember]
public string Name{get; set;}
static IEnumerable GetDerivedTypes()
{
return from type in typeof(Person).Assembly.GetTypes()
where typeof(Person).IsAssignableFrom(type)
select type;
}
}
[DataContract]
public class Student: Person
{
[DataMember]
public string Grade{get; set;}
}
[DataContract]
public class Teacher : Person
{
[DataMember]
public string Subject {get; set;}
}
public class MySerializer
{
var mySerializer = new DataContractSerializer(typeof(Person));
var stream = new MemoryStream();
var writter = new XMLTextWritter(stream, Encoding.UTF8) {Formatting = Formatting.Indented};
mySerializer.WriteObject(writter, new Teacher());
writter.flush();
Console.Writeline(stream);
}
Thursday, July 18, 2013
RESTful WCF Service
[ServiceContract]
public interface IBlogService
{
[OperationContract]
[WebInvoke(Method="GET", BodyStyle=WebMessageBodyStyle.Bare, RequestFormat= WebMessageFormat.Json, UriTemplate = "Blog/{id}")]
BlogPost GetBlogPost(string id);
[OperationContract]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, UriTemplate = "Blog/All")]
List GetAllPosts();
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, UriTemplate = "AddBlog/{id}")]
BlogPost PostBlog(string id, BlogPost post);
[OperationContract]
[WebInvoke(Method = "PUT", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, UriTemplate = "UpdateBlog/{id}")]
void PutBlog(string id, BlogPost post);
[OperationContract]
[WebInvoke(Method = "DELETE", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, UriTemplate = "DeleteBlog/{id}")]
void DeleteBlog(string id);
}
[DataContract]
public class BlogPost
{
[DataMember]
public string Id { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Content { get; set; }
[DataMember]
public string Labels { get; set; }
}
public class BlogService : IBlogService
{
static List posts = new List
{
new BlogPost{ Id = "1", Title= "Web Api Framework on .NET", Content = "services exposed over plain HTTP", Labels= "" },
new BlogPost{ Id = "2", Title= "MVC4", Content= "Mobile Support", Labels= "" },
new BlogPost{ Id = "3", Title = "KnockoutJS", Content= "Javascript based MVVM framework", Labels= ""}
};
public BlogPost GetBlogPost(string id)
{
WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;
return posts.Find(m => m.Id == id);
}
public List GetAllPosts()
{
WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;
return posts;
}
public BlogPost PostBlog(BlogPost post)
{
WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;
posts.Add(post);
return post;
}
public void PutBlog(string id, BlogPost post)
{
var blog = posts.Find(m => m.Id == id);
blog.Title = post.Title;
blog.Content = post.Content;
}
public void DeleteBlog(string id)
{
var post = posts.Find(m => m.Id == id);
posts.Remove(post);
}
}
Wednesday, July 17, 2013
Javascript Patterns
Javascript Prototype Pattern
var TaxCalculator = function(data){
this.name = data.Name;
this.basic = data.Basic;
this.allowances = data.Allowances;
this.deductions = data.Deductions;
this.result = 0
}
TaxCalculator.prototype = {
CalculateTax: function(){
this.result = ((this.basic +this.allowances) - this.deductions)*0.1;
}
}
$(document).ready(function(){
var data = {Name:Alex, Basic:4000, Allowances:600, Deductions: 400};
var calc = new TaxCalculator(data);
calc.CalculateTax();
alert(calc.result);
});
Overridding a function in prototype pattern
TaxCalculator.prototype.CalculateTax = function(){
this.result = ((this.basic +this.allowances) - this.deductions)*0.2;
}
Namespaces in javascript
myNamespace = myNamespace || {};
myNamespace.TaxCalculator = function(data){
this.name = data.Name;
this.basic = data.Basic;
this.allowances = data.Allowances;
this.deductions = data.Deductions;
this.result = 0
}
myNamespace.TaxCalculator.prototype = {
CalculateTax: function(){
this.result = ((this.basic +this.allowances) - this.deductions)*0.1;
}
}
$(document).ready(function(){
var data = {Name:Alex, Basic:4000, Allowances:600, Deductions: 400};
var calc = new myNamespace.TaxCalculator(data);
calc.CalculateTax();
alert(calc.result);
});
Module Pattern
var TaxCalculator = function(data){
//private members
var name = data.Name;
var basic = data.Basic;
var allowances = data.Allowances;
var deductions = data.Deductions;
var result = 0;
return {
//public members
CalculateTax : function(){
result = ((basic + allowances) - deductions)*0.1;
return result;
}
};
}
$(document).ready(function(){
var data = {Name:Alex, Basic:4000, Allowances:600, Deductions: 400};
var calc = new myNamespace.TaxCalculator(data);
alert(calc.CalculateTax());
});
Thursday, June 27, 2013
How to enforce secure HTTP access to an ASP.NET MVC Application.
To ensure that your actions are called through only Https, you can decorate your action methods with RequireHttps attribute. But this will not work in your development server as usually the development box is not configured with HTTPS. Basically you need to to apply this attribute conditionally based on a configurable item. This can be achieved by creating a custom class that is derived from RequireHttpsAttribute and by overridding its OnAuthorization().
using System;
using System.Configuration;
using System.Web;
using System.Web.Mvc;
public class RequireSslAttribute : RequireHttpsAttribute
{
private const string EnableSslKey = "EnableSSLForMySite";
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentException("filterContext");
}
if (!IsHttpContextNull(filterContext) && !IsEnableSsl())
{
return;
}
BaseOnAuthorization(filterContext);
}
protected virtual void BaseOnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
}
protected virtual bool IsHttpContextNull(AuthorizationContext filterContext)
{
return filterContext.HttpContext == null;
}
protected virtual bool IsEnableSsl()
{
var enableSslForMySite = HttpRuntime.Cache.Get(EnableSslKey);
bool isEnableSsl = false;
if (enableSslForMySite == null)
{
string configEnableSsl = ConfigurationManager.AppSettings[EnableSslKey] ?? string.Empty;
isEnableSsl = (configEnableSsl.ToLower() == "true");
HttpRuntime.Cache.Insert(EnableSslKey, isEnableSsl);
}
else
{
bool.TryParse(enableSsl.ToString(), out isEnableSsl);
}
return isEnableSsl;
}
}
BaseController
[RequireSsl]
public abstract class BaseController : Controller
{
}
Tuesday, June 25, 2013
How to track Browser's Back button to prevent user to visit an already deleted entity.
Solutions:
There are 2 ways by which the user can come back to a deleted entity. 1. By typing the Url in the browser address bar. 2. By clicking on the browser back button just after deleting the entity. While option-1 is already taken care of by redirecting the user to an Add New screen but the second option certainly allows the user to update an entity that is already deleted. So the solutions described here are applicable for option-2 scenario.
Solution – 1: By tracking a deleted flag using a Hidden Field.The value of a hidden field is retained when you use the browser back/Forward button. So the value of a hidden field can be used to check if the user has clicked the browser back button to reach the current page.
The solution can be implemented by following three simple steps.
- A hidden field with default value “0” is added to all UI which provides the provision to delete an entity. This doesn’t work if we add it programmatically. It has to be added in the .cshtml file.
- Inside the success callback of the delete method, set the value of the hidden field to “1”.
- On document load, check the value of the hidden field. If it is “1” then the current entity is a deleted entity.
The idea here to use HTML5 History/State API (pushState, getState etc.) to modify the history entries by replacing the current state with a delete state after a delete operation is over. pustState() & replaceState(0 are the two methods used to add/modify the history entries. This changes the referrer that gets used in the HTTP Header for XMLHttpRequest object. Then use the HTML5 onhaschange event to check if the current state of the entity matches with any of the previous deleted state in the History.
During this research it is established that Internet Explorer version 9 or less doesn’t supports HTML5 History/State API. Further research on this lead us to History.js plug-in which gracefully supports HTML5 History/State API in all browsers including the browsers that don’t support HTML5. So the POC is done based on the same idea using the History.js.
Here are the steps to implement this solution.
- Add code to modify the history entry of the current state with a deleted state inside the success callback of the delete Ajax call.
- Bind a custom function to the statechange event to check if the current state matches with any previous deleted state in history. If a match is found then take necessary action to alert the user about it.
Based on the ease of development, it seems that Hidden Field approach is the best option available currently with only additional burden of adding a hidden field on all UI that provides the provision to delete an entity except search screens.
Resources:http://msdn.microsoft.com/en-us/magazine/ff690558.aspx http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ https://github.com/browserstate/history.js
Altering a SQL Table on Production
Altering a SQL Table to add a column on Production can be risky affair as it contains vital production data in it. The sql script given below gives an idea how to go for it. In the example below, the table is getting altered to add the new column [Column6].
USE <> GO BEGIN TRANSACTION SET QUOTED_IDENTIFIER ON SET ARITHABORT ON SET NUMERIC_ROUNDABORT OFF SET CONCAT_NULL_YIELDS_NULL ON SET ANSI_NULLS ON SET ANSI_PADDING ON SET ANSI_WARNINGS ON COMMIT BEGIN TRANSACTION GO CREATE TABLE dbo.Tmp_ ( [Key] [int] IDENTITY(1,1) NOT NULL, [Column1] [int] NOT NULL, [Column2] [int] NOT NULL, [Column3] [int] NULL, [Column4] [int] NOT NULL, [Column5] [varchar](50) NULL, [Column6] [int] NULL ) ON [PRIMARY] GO ALTER TABLE dbo.Tmp_TableName SET (LOCK_ESCALATION = TABLE) GO SET IDENTITY_INSERT dbo.Tmp_TableName ON GO IF EXISTS(SELECT * FROM dbo.TableName) EXEC('INSERT INTO dbo.Tmp_TableName ([Key],[Column1], [Column2],[Column3], [Column4], [Column5]) SELECT [Key],[Column1], [Column2],[Column3], [Column4], [Column5] FROM dbo.TableName WITH (HOLDLOCK TABLOCKX)') GO SET IDENTITY_INSERT dbo.Tmp_TableName OFF GO DROP TABLE dbo.TableName GO EXECUTE sp_rename N'dbo.Tmp_TableName', N'TableName', 'OBJECT' GO ALTER TABLE dbo.TableName ADD CONSTRAINT PK_TableName PRIMARY KEY CLUSTERED ( [Key] ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO ALTER TABLE [dbo].[TableName] WITH CHECK ADD CONSTRAINT [FK_TableName_FKTable1] FOREIGN KEY([Column1]) REFERENCES [dbo].[FKTable1] ([Key]) GO ALTER TABLE [dbo].[TableName] WITH CHECK ADD CONSTRAINT [FK_TableName_FKTable2] FOREIGN KEY([Column2]) REFERENCES [dbo].[FKTable2] ([Key]) GO ALTER TABLE [dbo].[TableName] WITH CHECK ADD CONSTRAINT [FK_TableName_FKTable3] FOREIGN KEY([Column3]) REFERENCES [dbo].[FKTable3] ([Key]) GO ALTER TABLE [dbo].[TableName] WITH CHECK ADD CONSTRAINT [FK_TableName_FKTable14] FOREIGN KEY([Column4]) REFERENCES [dbo].[FKTable4] ([Key]) GO ALTER TABLE [dbo].[TableName] WITH CHECK ADD CONSTRAINT [FK_TableName_Table5] FOREIGN KEY([Column5]) REFERENCES [dbo].[FKTable5] ([Key]) GO COMMIT