Web service proxy in ASP.NET MVC – how to avoid cross-site script warnings

In this article I will walk through the process of creation of web service proxy in ASP.NET MVC. This is specifically useful as a method of preventing cross-site scripting (XSS) warnings on web page. This is a feature of all modern web browsers and cannot be easily omitted as it enforces same origin policy. This sort of attack can happen when browser tries to download client script from outside of application domain – simply speaking when web browser downloads script from different location.

For the purpose of this demo I will use IP look-up web service available at http://ipinfodb.com/. This web service allows to obtain geodata for given IP address and can be extremely useful for in example centralizing map (i.e. Google maps or Bing maps) on user’s location.

Valid request should look like this: http://ipinfodb.com/ip_query.php?ip=213.180.146.27

Of course it is possible to call this web service at Ajax request level, by simply writing:

    var ipaddress = '213.180.146.27';
    $.get('http://ipinfodb.com/ip_query.php?ip=' + ipaddress + '&timezone=false',
        function(data) {...}
    );

although on all most recent web browsers (IE 8, FF 3.6, Chrome, Safari) user will get very ugly security warning every time browser executes this code. This is due to XSS vulnerability mentioned above and can be extremely annoying to user when application performs this operation on very first page load.

Thankfully ASP.NET provides set of mechanisms to overcome this problem. In simplest words there is an extra layer between web service and Ajax call needed, and this layer is web service proxy.

The core component of proposed solution is a HTTP handler class, in this example named LocationProxyHandler. This class will create and execute HTTP request to web service and return response to client. It needs to implement two interfaces: IHttpHandler and IRouteHandler. First interface guarantees that class can process HTTP request, second allows to use class in routing rule that will be required to redirect requests to the handler class. Implementation of class is as follows:

    public class LocaionProxyHandler : IHttpHandler, IRouteHandler
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            string ipAddress = context.Request.QueryString["ipaddress"];

            string str = string.Format(@"http://ipinfodb.com/ip_query.php?ip={0}",
                ipAddress);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(str);
            request.Method = "GET";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());

            HttpResponse res = context.Response;
            res.ContentType = "application/xml; charcode=utf8";
            res.StatusCode = 200;
            res.Write(reader.ReadToEnd());
        }

        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return this;
        }
    }

The most important method in the class is ProcessRequest(). It takes current HttpContext as parameter and for this context it executes HTTP request to external web service and builds and returns response. Before it fires HTTP request, it takes IP address as parameter from URL.

There is one more thing that needs doing before this proxy can serve the purpose. It has to be registered in ASP.NET MVC routing table within the application. To accomplish this the following code is needed in RegisterRoutes() method inside Global.asax.cs:

    routes.Add(new Route("{action}.proxy", new SocialCitiProxy.LocaionProxyHandler()))

This makes calls like http://localhost:1431/myApp/Service.proxy understandable for MVC engine and ensures the request is redirected to LocationProxyHandler.

Very final step is Ajax request to LocationProxyHandler:

var ipaddress = '213.180.146.27';
$.ajax({
        url: 'GetUserLocation.proxy',
        data: 'ipAddress=' + ipaddress,
        dataType: 'xml',
        contentType: 'application/xml; charset=utf8',
        error: function (xhr, status, e) {...},
        success: function (data) {...}
});

No security warning messages appears now and this is exactly what we wanted to achieve.

Clustered vs. Non-clustered indexes in SQL Server

In this article I will make attempt to outline differences between clustered and non-clustered indexes in SQL Server. Be fully aware that it is not going to be comprehensive explanation, but rather brief overview highlighting purpose of both types of indexes.

Indexes

Indexes are one of the most important part of database optimization, especially for large and growing database tables. They work in very similar way to index in a book – just imagine massive address book, with thousands pages but no index. Searching this book for specific address is nearly impossible without index.

When query is ran against SQL Server database, Query Optimizer analyses all available indexes for tables involved, and creates most efficient execution plan to run statement. SQL Server reads data in 8KB pages, so if table is small enough to fit on one or two pages, there is no need for an index at all, as SQL Server will only have to make one or two read operations. This operation is called Full Table Scan and for small table it is the most efficient way of pulling the data out. On the other hand, if table has 1,000,000 records and size of row allows reading only 50 rows per page, number of read operations rises to 20,000. That clearly will take a lot of time and this is where indexes come into play. Indexes can massively improve SQL query, however is worth mentioning, that it does not come for free – indexes can take a lot of storage. When index is involved in selecting data from table, this operation is called Index Seek. In general we can distinguish two types of indexes: clustered and non-clustered.

Clustered Index

This index assumes that data in a table is physically sorted in specific order. This means that when new row is inserted, it physically goes to the place determined by index, allowing data after new row to be moved to next page if required. The table can only have one clustered index. This index is specifically useful if we use BETWEEN statement in WHERE clause of our statement (i.e. SELECT * FROM Table WHERE Col1 BETWEEN ‘A’ AND ‘Z’).

Non-clustered Index

When this type of index is used logical order of index does not match physical order of data stored on the disk. Index plays a role of “pointer to row”, allowing faster access to the row that is requested.

A non-clustered index is a special type of index in which the logical order of the index does not match the physical stored order of the rows on disk. The leaf node of a non-clustered index does not consist of the data pages. Instead, the leaf nodes contain index rows. This type of index works best when used having = in WHERE clause (i.e. SELECT * FROM Table WHERE Col1 = ‘A’) or if the column is used in JOIN.

Reference