Performance tips - GZIP compression


Adding on the performance tips for your asp.net site, using gzip compression for request and response can improve the network usage by more then 90%

 

Following is the step to do that:

First you need to add a httpmodule to your web application. Following is the code

 

namespace SecureFN.Common.Compression

{

 

    public class CompressionModule : IHttpModule

    {

        public void Dispose()

        {

        }

 

        public void Init(HttpApplication app)

        {

            app.PreRequestHandlerExecute += new EventHandler(Compress);

        }

 

        private void Compress(object sender, EventArgs e)

        {

            HttpApplication app = (HttpApplication)sender;

            HttpRequest request = app.Request;

            HttpResponse response = app.Response;

 

            //Ajax Web Service request is always starts with application/json

            if (request.ContentType.ToLower(CultureInfo.InvariantCulture).StartsWith("application/json"))

            {

                //User may be using an older version of IE which does not support compression, so skip those

                if (!((request.Browser.IsBrowser("IE")) && (request.Browser.MajorVersion <= 6)))

                {

                    string acceptEncoding = request.Headers["Accept-Encoding"];

 

                    if (!string.IsNullOrEmpty(acceptEncoding))

                    {

                        acceptEncoding = acceptEncoding.ToLower(CultureInfo.InvariantCulture);

 

                        if (acceptEncoding.Contains("gzip"))

                        {

                            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);

                            response.AddHeader("Content-encoding", "gzip");

                        }

                        else if (acceptEncoding.Contains("deflate"))

                        {

                            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);

                            response.AddHeader("Content-encoding", "deflate");

                        }

                    }

                }

            }

        }

    }

}

 

Second step is to add the entry in web.config

For IIS6 add the handler to httpModules, for IIS7 add modules

<add name="CompressionModule" type="Compression.SecureFNCompressionModule"/>

 

Next and last step is to add this to your requests. For example, while using jquery post, add following:

        contentType: "application/json;charset=utf-8",

 dataType: "json",

        processdata: true,

        beforeSend: function (request) {

            request.setRequestHeader("Accept-Encoding", "gzip");

        }

 

 

author: AnkitAgrawal | Posted On Thursday, March 8, 2012 10:12 PM | Comments (0)

Mac type grid view control for asp.net/java web applications


Mac type grid view control for asp.net/java web applications

 

For one of my project, I made a very dynamic grid which is totally HTML based and very fast while rendering data from server.

 

Features:

1.       No viewstate

2.       Dynamic grid which gets data on scroll using REST based WCF service in JSon

3.       No DOM modifications which makes the rendering very fast

4.       Custom control which can be integrated in any web application – Java / Asp.Net (However I built it for Asp.Net)

5.       Support for very large record set.

6.       Designer friendly – As the DOM doesn’t change and the basic structure remains the same.

7.       Highly extensible to support any kind of data

 

Concept:

The concept comes from Apple applications and IPhone/IPad where user is provided with very rich user interface which allows him to scroll through the records very fast. Actually what happens is that the basic structure of the grid remains the same (the table , tr, etc.) all that gets modified is the content of the control. For example, if we talk about a link button, only attributes that are modified are text, url. Rest remains the same. This is what will make the grid to function very fast as you are actually not modifying the DOM object from client but modifying some attributes which again would give better performance.

On UI, the grid is divided into two parts –

1.       Actual grid which will show the actual content. This would basically be the table with TR’s inside. The table will have overflow as false so that this grid doesn’t have a scroll bar. The content of this portion will be modified on scroll which is explained in the second part.

2.       Second Div which will have the scroll bar. The concept here would be to insert another Div in this which will have height = Total number of records * height of each TR. This would generate a scrollbar for user. The only thing that needs to be handled now is the scroll event.

Implementation (ASP.NET)

Basically this grid was designed for an ASP.NET project but can eventually be used in java also as it basically works on the basic html tags of HTML. I created a custom control here that would override the render mechanism of a WebControl.

Basic Architecture

The grid basically is a table with multiple number of TR and TD both getting derived from the user input. TD, user would give the column specification for grid in its definition in aspx.

 

<cc1:MashableGrid ID="myGrid" runat="server" ItemCss="row1" AlternatingItemCss="row2"

                        DataKeyColumnName="KeyId" Width="98.5%" Rows="10" Height="330"

                        DefaultSortExpression="KeyId" ServiceName="/BusinessService/GetData"

                        HeaderCss="tableHeader" RequestDelay="250" QStringColumnName="KeyId">

                        <Columns>

                            <Items>

                                <cc1:Column Width="10%" CssClass="boldFont tab_coloum_border"

                                    AllowSorting="true" AllowSearching="true" SortExpression="RoleName" DataFieldName="Name"

                                    DisplayProperty="IsDisplay" DataType="System.String">

                                    <Controls>

                                                                                    <asp:LinkButton ID="lnkBtn" Text="Name" IsResourceKeyRequired="false"

                                                EncryptedQStringColumnName="KeyId" ToolTip="Name" ClientClickFunction="EditName" />

                                       

                                    </Controls>

                                </cc1:Column>

                            </Items>

                        </Columns>

                    </cc1:MashableGrid>

 

What basically goes at the back is that a json collection is expected to the javascript code which basically replaces the control properties on the page with the ones mentioned in the json collection.

  


Let’s call the first div (big one) as DivMain. This div will have the main table which will actual data.

The div on the right is a composite grid with another grid into it. Lets call it DivScroller and this is having another div with name DivDummy.

DivMain has its overflow set to hidden and would never ever show scroller. All it will show is a table of content.

DivScroller having another div in it has overflow set to auto. This acts just as a container to another div which is the main thing that plays in this control. The height of this div would be set dynamically to show scroller in the parent div (DivScroller). Calculation is as follows

Height of DivDummy = total number of records * height of each td (DivMain)

By this you would achieve the desired scroller. Now binding the scroll event of this grid and displaying the data according to the scroll position is the main task left.

This would be achieved by a little calculation on the basis of scroll position

Start record to show = scrollPosition / height of each td(DivMain)

Now only thing left in code is how to get the data and bind it. So on scroll, there would be a service call that would ask for data from server (according to start count and number of records that are displayed).

Next thing and the biggest task left is to map and replace the content according to the data we got in json. If you saw it, we specified some properties while binding the grid (in aspx). That will play the trick. Every html control has max 3-4 attributes that are actually dynamic and are set. And this is what we will replace. Below is the code that does the trick.

 

MashableTree.prototype.FillData = function (list, mashTree) {

    if (list == undefined || list == null || list.length == 0) {

        $('#' + this.actualGridId + ' td').each(function () {

            this.style.display = 'none';

        });

        $('#' + this.actualGridId + ' th').each(function () {

            this.style.display = 'none';

        });

        return;

    }

    var mapping;

    var typeArr;

    var types = '';

    var type = '';

    var dataType = '';

    var strMappings = new Array();

    var map = new Array();

    var index = 0;

    var td = null;

    $('#' + this.actualGridId + ' td').each(function () {

        td = $(this);

        mapping = $(td).attr('mapping');

        dataType = $(td).attr('DataType');

        if (mapping != undefined) {

            types = $(td).attr('type');

            index = $(td).attr('index');

            typeArr = types.split(',')

            for (var t = 0; t < typeArr.length; t++) {

                type = typeArr[t];

                switch (type) {

                    case 'key':

                        str = mapping.split(',');

                        for (var i = 0; i < str.length; i++) {

                            if (str[i] != '') {

                                map = str[i].split(':');

                                if (map[0] == 'key') {

                                    if (index < list.length) {

                                        var id = parseInt(mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]));

                                        $(td).text(id.toString());

                                        if (mashTree.SelectedFolderId > 0) {

                                            if (mashTree.SelectedFolderId == id) {

                                                $(td).parent().addClass('SelectedTD');

                                            }

                                        }

                                    }

                                }

                            }

                        }

                        break;

                    case 'lnk':

                        str = mapping.split(',');

                        for (var i = 0; i < str.length; i++) {

                            if (str[i] != '') {

                                map = str[i].split(':');

                                if (map[0] == 'td_disp') {

                                    if (index < list.length) {

                                        var dispVal = mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]);

                                        if (!dispVal) {

                                            $(td).children().hide();

                                            break;

                                        }

                                        else {

                                            if (mapping.indexOf('img') < 0) {

                                                $(td).children().show();

                                            }

                                        }

                                    }

                                }

                                else {

                                    if (mapping.indexOf('img') < 0) {

                                        $(td).children().show();

                                    }

                                }

                                if (map[0] == 'lnk_text') {

                                    if (index >= list.length) {

                                        $(td).children()[0].innerHTML = '';

                                    }

                                    else {

                                        $(td).children()[0].innerHTML = mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]); // list[index][map[1]];

                                    }

                                }

                                if (map[0] == 'lnk_url') {

                                    if (index >= list.length) {

                                        $(td).children()[t].href = '';

                                    }

                                    else {

                                        if (map[1] != '') {

                                            $(td).children()[t].href = mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]); // list[index][map[1]];

                                        }

                                        else {

                                            $(td).children()[t].href = '#';

                                        }

                                    }

                                }

                                if (map[0] == 'lnk_function') {

                                    if (map[1].length > 0) {

 

                                        if (index >= list.length) {

                                            $(td).children().hide();

                                        }

                                        else {

                                            var tdHtml = $(td).html();

                                            var functionHtml = '';

                                            var indexStart = 0;

                                            var indexEnd = 0;

                                            var textToReplace = '';

                                            if (tdHtml != '') {

                                                indexStart = tdHtml.indexOf(map[1]);

                                                indexEnd = tdHtml.indexOf(';', indexStart);

                                                textToReplace = tdHtml.substring(indexStart, indexEnd + 1);

                                                if (mashTree.QStringColumnName != '') {

                                                    tdHtml = tdHtml.replace(textToReplace, map[1] + "('" + list[index][mashTree.QStringColumnName] + "');");

                                                    $(td).html(tdHtml);

                                                }

                                            }

                                        }

                                    }

                                }

                            }

                        }

                        break;

                    case 'lbl':

                        str = mapping.split(',');

                        for (var i = 0; i < str.length; i++) {

                            if (str[i] != '') {

                                map = str[i].split(':');

                                if (map[0] == 'td_disp') {

                                    if (index < list.length) {

                                        var dispVal = mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]);

                                        if (!dispVal) {

                                            $(td).html('');

                                            $(td).children().hide();

                                            break;

                                        }

                                        else {

                                            $(td).children().show();

                                        }

                                    }

                                }

                                else {

                                    $(td).children().show();

                                }

                                if (map[0] == 'lbl_text') {

                                    if (index >= list.length) {

                                        $(td).text('');

                                    }

                                    else {

                                        if (dataType == 'System.DateTime') {

                                            $(td).text(mashTree.ConvertToDate(mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1])));

                                        }

                                        else {

                                            $(td).text(mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]));

                                        }

                                    }

                                }

                            }

                        }

                        break;

                    case 'img':

                        if (index >= list.length) {

                            $(td).children().hide();

                            break;

                        }

                        else {

                            $(td).children().show();

                        }

                        str = mapping.split(',');

                        for (var i = 0; i < str.length; i++) {

                            if (str[i] != '') {

                                map = str[i].split(':');

                                if (map[0] == 'td_disp') {

                                    if (index < list.length) {

                                        var dispVal = mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]);

                                        if (!dispVal) {

                                            $(td).children().hide();

                                            break;

                                        }

                                        else {

                                            $(td).children().show();

                                        }

                                    }

                                }

                                else {

                                    $(td).children().show();

                                }

                                if (map[0] == 'img_url') {

                                    if (map[1].length > 0) {

                                        if (index >= list.length) {

                                            $(td).children()[t].style.display = 'none';

                                        }

                                        else {

                                            $(td).children()[t].style.display = '';

                                            $(td).children()[t].src = list[index][map[1]];

                                        }

                                    }

                                }

                                if (map[0] == 'img_display') {

                                    if (map[1].length > 0) {

                                        if (index >= list.length) {

                                            $(td).children()[t].style.display = 'none';

                                        }

                                        else {

                                            if (list[index][map[1]]) {

                                                $(td).children()[t].style.display = '';

                                            }

                                            else {

                                                $(td).children()[t].style.display = 'none';

                                            }

                                        }

                                    }

                                }

                                if (map[0] == 'img_function') {

                                    if (map[1].length > 0) {

 

                                        if (index >= list.length) {

                                            $(td).children().hide();

                                        }

                                        else {

                                            var tdHtml = $(td).html();

                                            var functionHtml = '';

                                            var indexStart = 0;

                                            var indexEnd = 0;

                                            var textToReplace = '';

                                            if (tdHtml != '') {

                                                indexStart = tdHtml.indexOf(map[1]);

                                                indexEnd = tdHtml.indexOf(';', indexStart);

                                                textToReplace = tdHtml.substring(indexStart, indexEnd + 1);

                                                if (mashTree.QStringColumnName != '') {

                                                    tdHtml = tdHtml.replace(textToReplace, map[1] + "('" + list[index][mashTree.QStringColumnName] + "');");

                                                    $(td).html(tdHtml);

                                                }

                                            }

                                        }

                                    }

                                }

                            }

                        }

                        break;

                    case 'chk':

                        str = mapping.split(',');

                        for (var i = 0; i < str.length; i++) {

                            if (str[i] != '') {

                                map = str[i].split(':');

                                if (map[0] == 'td_disp') {

                                    if (index < list.length) {

                                        var dispVal = mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]);

                                        if (!dispVal) {

                                            $(td).children().hide();

                                            break;

                                        }

                                        else {

                                            $(td).children().show();

                                        }

                                    }

                                }

                                else {

                                    $(td).children().show();

                                }

                                if (map[0] == 'chk_checked') {

                                    if (index >= list.length) {

                                        $(td).children()[t].style.display = 'none';

                                    }

                                    else {

                                        $(td).children()[t].style.display = '';

                                        $(td).children()[t].checked = mashTree.GetDataFromList(mashTree, list, parseInt(index), map[1]);

                                    }

                                }

                            }

                        }

                        break;

                    default:

                        {

                            if (index >= list.length) {

                                $(td).children()[t].style.display = 'none';

                            }

                            else {

                                $(td).children()[t].style.display = '';

                            }

                            break;

                        }

                }

            }

        }

    });

}

 

If you want to use this grid, I can share the code. Drop a comment on this post along with the email id.

author: AnkitAgrawal | Posted On Monday, February 6, 2012 1:56 AM | Comments (1)

Uniqueness of SessionId and GUID



Random and unique are two different words with very different meaning. To generate random number, there are many algorithms but none to guarantee unique number. This causes a problem of non-unique GUID and SessionId generated in any application whether you use .NET / java / php. (I have seen this in ASP.NET and java). If you grill down to the algorithm that is used to create SessionId, it does never guarantee a unique number whenever it is generated. 


When you hover over the SessionId in ASP.NET application in VS, it says Unique SessionId. I don’t know how they can guarantee a unique id when there algorithm doesn’t support so. Below is the code:


internal static string Create(ref RandomNumberGenerator randgen)

{

    if (randgen == null)

    {

        randgen = new RNGCryptoServiceProvider();

    }

    byte[] data = new byte[15];

    randgen.GetBytes(data);

    return Encode(data);

}

private static string Encode(byte[] buffer)

{

    char[] chArray = new char[0x18];

    int num2 = 0;

    for (int i = 0; i < 15; i += 5)

    {

        int num4 = ((buffer[i] | (buffer[i + 1] << 8)) | (buffer[i + 2] << 0x10)) | (buffer[i + 3] << 0x18);

        int index = num4 & 0x1f;

        chArray[num2++] = s_encoding[index];

        index = (num4 >> 5) & 0x1f;

        chArray[num2++] = s_encoding[index];

        index = (num4 >> 10) & 0x1f;

        chArray[num2++] = s_encoding[index];

        index = (num4 >> 15) & 0x1f;

        chArray[num2++] = s_encoding[index];

        index = (num4 >> 20) & 0x1f;

        chArray[num2++] = s_encoding[index];

        index = (num4 >> 0x19) & 0x1f;

        chArray[num2++] = s_encoding[index];

        num4 = ((num4 >> 30) & 3) | (buffer[i + 4] << 2);

        index = num4 & 0x1f;

        chArray[num2++] = s_encoding[index];

        index = (num4 >> 5) & 0x1f;

        chArray[num2++] = s_encoding[index];

    }

    return new string(chArray);

}


author: AnkitAgrawal | Posted On Monday, February 6, 2012 1:55 AM | Comments (0)

Size of object in .Net


I am here to take your attention on size of .Net object when we call a service. This will help when you want to find out the size of .net object in a service call. This might happen when you face a buffer overrun problem.

While trying to debug a service call, where we suspect a buffer overrun situation, we wanted to find out the size of object being returned by a service call. However finding size of .net object is not trivial and if you thought that you can do it with sizeof(object), and then you are wrong. This will only return the size of object based on the size of each field in object that itself is based on the type of the field. This does not return the size of the object in memory with data loaded into it. 

Another option people try to use it Marshal.Sizeof(object), but this gives the size of unmanaged representation of the object and the layout in managed and unmanaged world may be very different.

Chris Brumme(earlier was in CLR Team) had written that there is no direct API in .net to provide this size and he has explained it here.

Some forums talk about using the serialization approach. So you essentially create a memory stream and then use binary formatter and serialize the object in the stream and then the size of the stream. The size thus obtained is really the serialized size not in the memory size. Why will the two differ?

These can differ for:

1. The layout of the object in memory/byte alignment etc. will cause the difference.

2. If the object overrides and custom serialization, it might after what all gets serialized and thus the size will differ.

Another option that possibly best according to me is to use GC.GetTotalMemory() API before and after the call to create the object. See details here.However this itself has its own challenges in that it is not thread safe, as the blogs also point out. Multiple things can happen between two calls to GC and other threads may release or allocate other objects and hence the size difference you will get may not truly reflect the size of only this object. Another aspect is that this object itself may need multiple steps to fully populate and hence enclosing these steps within calls to GC.GetTotalMemory() may be tricky.

There is one last option, which will be mostly 100% accurate, and this is to take the memory dump of the process once the object is allocated and then using WinDBG find out the total size of the object by using the objsize command.  See some explanation how to use WinDBG for this purpose here.

 

Hope it will help all of you if you have any issues related to this. 

Till next time and welcome all for your valuable comments.

Thanks 

author: AnkitAgrawal | Posted On Tuesday, October 11, 2011 6:34 PM | Comments (0)

Performance Optimization tips for ASP.NET application


For more formatted view .. Goto http://ankitagrawal57.blogspot.com/

For any web application, performance is basic necessity. Earlier internet speed used to be limited thus users got inclined to pages which load within 3-4 secs. But now the internet speed is no more a constraint but still time does remain a constraint. Imagine yourself visiting a website which takes a lot of time (30 – 60 secs) just to load the page. You would not like to go to that site again.

To mitigate this issue, developers and designers work a lot towards improvement of performance. I too worked on this and found out some key things that might be useful to others. I am not reinventing the tips, I am just trying to collate all the tips that I found useful while my development and performance optimization. Starting off with the UI, I will list down all key features that can be used to improve performance. Hope the journey with this document goes well. Please provide any comment or feedback if you feel otherwise. I would be more than happy to incorporate it.

1. Web Controls

a. Page: 

i. Avoid Tables. Use Div,span in place of them.

ii. Place CssClass instead of assigning style on tag. This will reduce the text in html file (as only one class name is replaced by multiple styles)

iii. Join Css, Js files.

iv. Use Css in place of Javascript wherever possible. For example, for hover, use Css class instead of writing JS.

v. Use multiple servers for parallel downloads of resources.

b. Custom Controls: If you are making a custom control or overriding the render mechanism of a control, keep in mind following things:

i. Using Div,Span tags adds to performance in comparision to Table. For example, Asp.net Treeview control uses Table/Tr/Td to render the treeview. This makes this control heavy. Use can make your own custom control which renders in Div/Span and will give better performance when playing with large data (2000 treenodes).

ii. IE (6-8) works in a weird way with long string. If your control is big with many html tags or a series of tags (like 2000 treenodes for a custom tree view), IE will take time to render that control. Placing Environment.NewLine in the tags somehow increases the performance. 

2. Javascript

a. Javascript accelerator on IE: One common issue that developers face – Page opens up fast in Firefox and chrome while it takes a hell lot of time on IE (6-8). In my case, IE used to hang and then restart itself after 30-40 seconds. This issue due to the rendering engine that browsers use. IE (6-8) uses Trident (3,4 version). This didn’t have hardware acceleration for javascript and jquery. Other engines (Chrome, Firefox) uses hardware accelerator for javascript. This was problem when page have a lot of javascript which will iterate through the whole page and search for an object. So any loop in javascript (with 1000 or more iteration will have performance impact). Check it out here.

b. Modifying DOM object: Remember that modifying a DOM object in javascript will impact the performance of the web page.

c. Compress Javascript: The javascript you deploy on test or production server should be well compressed. This will again improve the performance as the compressed file be of less size and smaller variable names. Freely available tools are 

i. http://dean.edwards.name/packer/

ii. http://javascriptcompressor.com/

d. Jquery Selector: Use Jquery selector wisely. What it does internally is, iterate through all the DOM objects in the page and select the objects that meets the criteria. Prefer using :First, :Last, etc. Or put a wrapper element (like div) and run the selector on that. This will reduce the number of objects to be searched. 

i. Try avoiding selector on class name. Instead try to select the element by id. Class selector will iterate through the whole DOM object while element selector will break when it finds the element.

3. Service: Use REST based WCF service for fetching or updating data. REST service is faster and can be cached. So application will gain performance.

4. Database (SQL Server 2008)

a. Use following where ever applicable:

i. Use “Exists” more. It serves with better performance.

ii. Use CTE (Common Table Expressions) instead of temporary table 

b. Following 2 Procedures have different performance. If you see the plan for execution in both the case, it will be apparent that the second one will have more “Estimated Number of Rows”. While first one will have only 1.

(Note: ID is Primary Index field in Table1.)

i. Create ProcName 

  @Id Int

AS

BEGIN

  Select * from Table1 Where Id = @Id

END

ii. Create ProcName 

  @Id Int

AS

BEGIN

Declare @myId int

Set @myId = @Id

  Select * from Table1 Where Id = @myId

END

This is because the first one will be considered as constant and thus the execution plan will estimate that the rows to scan is 1 while in second case, the execution plan would be different

c. Service Broker: This new technology, a part of the Database Engine, provides a message-based communication platform that enables independent application components to perform as a functioning whole. Service Broker includes infrastructure for asynchronous programming that can be used for applications within a single database or a single instance as well as for distributed applications.


author: AnkitAgrawal | Posted On Wednesday, September 21, 2011 3:22 AM | Comments (3)

Use EF 4.0 or not ?


At the beginning I want to inform that I've already read the similar question here: Entity Framework 4.0: is it worthy now? but it does not answer my questions and doubts concerning EF 4.0. Here's the case: We are working on a quite big project written in WPF and WCF. The structure of the database contains about 60 tables, lots of stored procedures, views and some functions. We are not using any ORM at the moment. Some time ago when the first version of EF was release we did not go with it because of the known reasons: 1. one threaded only (it uses only one processor core) 2. no support for lazy loading 3. no support for POCO 4. horrible designer 5. no support for foreign keys (as far as I remember) 6. horrible mappings support (as far as I remember I needed to use lots of hacks and workarounds) I think we can all agree that this version of EF was rather "TOY" than a reasonable "TOOL". I remember that calling SaveChanges() method on my entity model with a complex hierarchy took quite long time and looking at SQL Profiler I was confused seeing "SQL queries explosions". Therefore we decided to use repository pattern and repository locator pattern and write plain ADO.NET queries. This works fine so far, however sometimes we see that code maintence is hard. Additionally we use our own deserializers to materialize objects. At the moment we think about using Entity Framework 4.0. I know there are many improvements and enhancements in this framework and it's fine to use it in small projects. Therefore my question are: 1. what are pros and cons using EF 4.0 and what will be the consequence of using it in a bigger project? 2. how about SQL Queries generated by EF 4.0? Is the performance increased? 3. can EF 4.0 use all processor cores? 4. should we use it now or wait for EF 5.0 where Code first will be supported?

author: AnkitAgrawal | Posted On Tuesday, September 20, 2011 4:16 AM | Comments (0)

Windows phone 7 - Why does it not support unmanaged code?


I went through a lot api's for windows phone 7 and couldnt find a single way to include my unmanaged code in it. Is there any way to do the same. If not why is it so ? Even in .net, microsoft allows unmanaged code to be included.

author: AnkitAgrawal | Posted On Wednesday, September 7, 2011 1:31 PM | Comments (2)