Thursday, March 31, 2011

Cross domain page request using jquery

Have you ever wanted to display content from another domain into you site using client side scripts? At this moment you may already know it is not possible make ajax request to a different domain or subdomain using javascript, since it violates the same origin policy

Luckily, there is a work around to it.

You can achieve this by including a proxy page that is dedicated to making a server side request to the intended page in the other domain and return the contents retrieved as its own content. How cool is that? J

Then you can make ajax request to the proxy page using jquery and further filter the content using selectors and integrate it into your Page.

The code below demonstrates how to load content from www.example.com .

Proxy page: uses System.Net classes to make http request and receive the response .If the request is successful, i.e. Status Code is 200, and it will read the response stream from the cross domain request and return the content read in its response.

Proxy.aspx.cs:

using System;

using System.IO;

using System.Net;

namespace CrossDomainPageRequestSample

{

public partial class Proxy : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

// ‘loadUrl‘ is the address to the page in the other domain

var url = Request.QueryString["loadurl"];

// create a request

HttpWebRequest request = (HttpWebRequest)

WebRequest.Create(url);

// make the request

var response = (HttpWebResponse)request.GetResponse();

// we will read data via the response stream

if (response.StatusCode == HttpStatusCode.OK)

{

var contentReader = new StreamReader(response.GetResponseStream());

Response.ContentType = response.ContentType;

Response.Write(contentReader.ReadToEnd());

}

}

}

}

Proxy.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Proxy.aspx.cs" Inherits="CrossDomainPageRequestSample.Proxy" %>

DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<title>title>

head>

<body>

<form id="form1" runat="server">

<div>

div>

form>

body>

html>

DefaultPage:

This page makes Ajax request to the Proxy page and filters the content returned and appends to the div with id ‘otherSiteContent’.

$('#otherSiteContent').load('proxy.aspx?loadurl=http://www.example.com/ #header', function () { });

Default.aspx

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"

CodeBehind="Default.aspx.cs" Inherits="CrossDomainPageRequestSample._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">

<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.min.js">

script>

<script type="text/javascript">

$(document).ready(function () {

// the script below loads the proxy page and further applies id selector #header and appends the content to

// the div #otherSiteContent

$('#otherSiteContent').load('proxy.aspx?loadurl=http://www.example.com/ #header', function () {

});

});

script>

asp:Content>

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">

<div>

div>

Page Content from the other site goes below

<div id="otherSiteContent">

div>

asp:Content>

DefaultPage.aspx.cs

using System;

namespace CrossDomainPageRequestSample

{

public partial class _Default : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

}

}

}

Wednesday, March 30, 2011

Controlling the Serialization process by implementing ISerializable

In my current project we keep items in the cache to share them among multiple requests. When items are added to the cache they are serialized by the runtime. However, the default serialization process makes use of reflection to determine the object structure, its contents and relationship with other objects and serializes all public and protected fields. Thus the cached items size tends to be large and the process is a bit slower.

Thus to alleviate the problems described above, I wanted to have a fine grained control on the serialization process and explicitly state which fields are to be serialized and avoid using reflection to determine the object properties.

Fortunately .Net allows you to control the serialization process in many ways. However, this topic demonstrates how to achieve this result by extending the ISerializable class.

Steps to follow

1. The class to be serialized should to be decorated by [Serializable] attributes.

2. The class needs to extend ISerializable in System.Runtime.Serialization. In doing so you will implement GetObjectData(SerializationInfo info, StreamingContext context). Inside this method you will access the serialization info and provide alternate values for the fields to be serialized as namevalue pairs. Later the serializer will make use of the new values.

3. Provide a second constructor like

Employee (SerializationInfo info, StreamingContext context).

In this constructor, access the serialization info to reconstruct the serialized fields.

Note: a derived class needs to call the base class’s new constructor (i.e. the base class should also implement Iserializable) to recover the serialized fields. Or alternatively, the derived class needs to serialize/deserialize the fields of the parent class.

The following code puts all the pieces together. Besides it shows you how to serialize a collection property.

[Serializable]

public class Employee : ISerializable

{

public string Name { get; set; }

public int Id { get; set; }

public IEnumerable&lt;Address> Addresses { get; set; }

public Employee()

{

}

public Employee(SerializationInfo info, StreamingContext context)

{

Name = info.GetString("N");

Id = info.GetInt32("Id");

Addresses = (List&lt;Address>) info.GetValue("Addresses", typeof (List&lt;Address>));

}

public void GetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue("N",Name);

info.AddValue("Id",Id);

info.AddValue("Addresses",Addresses);

}

}

[Serializable]

public class Address:ISerializable

{

public string Street { get; set; }

public Address()

{

}

public Address(SerializationInfo info, StreamingContext context)

{

Street = info.GetString("St");

}

public void GetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue("St",Street);

}

}