Pages

Tuesday, October 19, 2010

How to consume RSS in ASP.NET 3.5

After a very long gap of routine development and coding of web applications, I found this to be more interesting, easy and fascinating for me(At the least to learn something new!). Straight away we can jump into the coding.

The requirement was to consume a RSS feed and show the top 5 feeds in the page(in a sub section).

Create a Web User Control:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="RssFeed.ascx.cs" Inherits="_controls_rss_feed" %>
<asp:Repeater ID="rptRssFeed" runat="server" >

    <ItemTemplate>
        <li>
            <h4><asp:Literal ID="litTitle" runat="server" Text='<%# Eval("Title") %>' /></h4> 
            <p><asp:Literal ID="litDescription" runat="server" Text='<%# Eval("Description") %>' /></p>
            <asp:HyperLink ID="hypLink" Text="Read More" runat="server" NavigateUrl='<%# Eval("Link") %>'                                  target="_blank" />
        </li>
    </ItemTemplate>    
</asp:Repeater>


Code Behind:

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;


public partial class _controls_RssFeed : System.Web.UI.UserControl
{
    # region Properties
    public string FeedUrl { get; set; }
    #endregion Properties
    #region Page Event
    protected void Page_Load(object sender, EventArgs e)
    {
        //Loads the RSS feed
        XElement rootElement = XElement.Load(FeedUrl);
        //Queries to pick the top 5 feeds/items order by date DESC - LINQ
        var feedItems = (from item in rootElement.Descendants("item")
                         orderby DateTime.Parse(item.Element("pubDate").Value) descending
                         select new
                         {
                             Title = item.Element("title").Value,
                             Description = item.Element("description").Value,
                             Published = DateTime.Parse(item.Element("pubDate").Value),
                             Link = item.Element("link").Value
                         }).Take(5);              
        //DataSource for the Repeater Control.
        this.rptRssFeed.DataSource = feedItems;
        this.rptRssFeed.DataBind();
    }
    #endregion Page Event
} 


So now the Re-Usable Web User Control is developed and ready to use across the application. 


Create a Page and Inherit the Web User Control: 
Just register the control and use it as as when needed. Here is the page code. 
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register src="_controls/RssFeed.ascx" tagname="RssFeed" tagprefix="uc" %>
<!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>  
           <uc:RssFeed ID="ctrRssFeed" runat="server" FeedUrl="http://rss.news.yahoo.com/rss/sports" /> 
        </div>
      </form> 
    </body> 
</html>


We have successfully created a control consuming a Rss Feed and inherited the control to the page. I hope 
this would have helped you or served your purpose. 

Have fun and happy coding.



Thursday, September 16, 2010

IIS7:Create website using .NET

This can be achieved in two ways. Earlier in IIS6 and below we use System.DirectoryServices. Now the .NET 3 new .NET library Microsoft.Web.Administration allows us to manage IIS settings very easy.

FirstWay:

AppPool Creation:

Private Sub CreateAppPool(ByVal appPoolMetabasePath As String, ByVal appPoolName As String)

Try
Dim newpool As DirectoryEntry
Dim apppools As DirectoryEntry

If appPoolMetabasePath.EndsWith("/W3SVC/AppPools") Then
apppools = Me.GetIISDirectoryEntry(appPoolMetabasePath)
newpool = apppools.Invoke("Create", "IIsApplicationPool", appPoolName)
newpool.CommitChanges()
Else
Throw New Exception("Failed in CreateAppPool(): Application pools can only be created in the */W3SVC/AppPools node.")
End If

Catch ex As Exception
Throw ex
End Try

End Sub

Function To Fetch Next SiteID:

Private Function GetNextSiteId(ByVal objService As DirectoryEntry) As String
Dim strNewSiteId As String = String.Empty
Dim siteIDNum As Integer = 1
For Each e As DirectoryEntry In objService.Children
If e.SchemaClassName = "IIsWebServer" Then
Dim ID As Integer = Convert.ToInt32(e.Name)
If ID >= siteIDNum Then
siteIDNum = ID + 1
End If
End If
Next
strNewSiteId = siteIDNum.ToString()
Return strNewSiteId
End Function

Craete Site and Assign To the AppPool:

Public Sub CreateSite(ByVal localPath As String, ByVal domainName As String, _
ByVal siteName As String, ByVal appPoolName As String)

Dim iisRootDirectory As DirectoryEntry
Dim sites As DirectoryEntries
Dim className As String
Dim websiteIdentificationName As String
Dim iisUnderNT As Boolean = False
Dim newSiteID As String
Dim iisAdminUserName As String
Dim iisAdminPassword As String

Try
iisAdminUserName = Utility.GetAppSettingsValue(Of String)(Utility.AppSettingsKey.IISAdminName)
iisAdminPassword = Utility.GetAppSettingsValue(Of String)(Utility.AppSettingsKey.IISAdminPwd)

' Impersonate the User with Admin User. ImpersonationManager is separete class.
Using impersonationManager As New ImpersonationManager(iisAdminUserName, iisAdminPassword, domainName)

If impersonationManager.impersonateValidUser() Then

iisRootDirectory = Me.GetIISDirectoryEntry("IIS://Localhost/W3SVC")
sites = iisRootDirectory.Children
className = iisRootDirectory.SchemaClassName.ToString()

'Determine version of IIS
Using iisRootSchema As DirectoryEntry = Me.GetIISDirectoryEntry("IIS://Localhost/Schema/AppIsolated")
If iisRootSchema.Properties.Item("Syntax").Value.ToString.ToUpper = "BOOLEAN" Then
iisUnderNT = True
End If
End Using

'SiteName for Ex: yahoo,google
websiteIdentificationName = siteName

If className.EndsWith("Service") Then
'1. Get New Site for the site to be created on IIS
newSiteID = Me.GetNextSiteId(iisRootDirectory)

'2. Create a new website and add to IISRoot and Autostart website
Dim newSite As DirectoryEntry = sites.Add(newSiteID, (className.Replace("Service", "Server")))

'3. Autostart Website
newSite.Invoke("Put", "ServerAutoStart", 1)
newSite.CommitChanges()

'4. Configure Host header information for subdomains configuration
Dim hostHeaders As Object() = {":80:" & websiteIdentificationName, ":80:www." & websiteIdentificationName}
newSite.Invoke("Put", "ServerBindings", hostHeaders)
newSite.CommitChanges()

'5. Set Authorisation flags
newSite.Invoke("Put", "AuthFlags", "1") '1 = AuthAnonymous, 2 = BasicAuth, 4 = AuthNTLM - integrated windows auth,16 = AuthMDS, 64 = AuthPassport
newSite.CommitChanges()

newSite.Invoke("SetInfo")
newSite.CommitChanges()

'6. Set .Net 2.0 Framework Version
Dim scriptMapVals As PropertyValueCollection = newSite.Properties("ScriptMaps")
Dim objScriptMaps As New ArrayList()
For Each scriptMapVal As String In scriptMapVals
If scriptMapVal.IndexOf("Framework") > 0 Then
Dim version As String = scriptMapVal.Substring(scriptMapVal.IndexOf("Framework") + 10, 9)
Dim strNewValue As String = scriptMapVal.Replace(version, "v2.0.50727")
' UGLY .. but framework version wasnt returning this value

objScriptMaps.Add(strNewValue)
Else
objScriptMaps.Add(scriptMapVal)

End If
Next
newSite.Properties("ScriptMaps").Value = objScriptMaps.ToArray()
newSite.CommitChanges()

'7. Set website name and description
Me.SetMetabaseSingleProperty(newSite, "ServerComment", websiteIdentificationName)

'8. Set Application Name
Me.SetMetabaseSingleProperty(newSite, "AppFriendlyName", websiteIdentificationName)

'9. Set Applcation Pool
Dim poolRoot As New DirectoryEntry("IIS://localhost/W3SVC/AppPools")
Dim pool As DirectoryEntry = poolRoot.Children.Add(appPoolName, "IIsApplicationPool")
'*****************************************************************
'Important: To set App Pool to run in Integrated Mode in IIS 7.0
'*****************************************************************
pool.InvokeSet("ManagedPipelineMode", New Object() {0})
pool.CommitChanges()

'10. Set Scripts Execute Permissions
Me.SetMetabaseSingleProperty(newSite, "AccessExecute", True)

'11. Set Default documents
Me.SetMetabaseSingleProperty(newSite, "DefaultDoc", "default.aspx, default.htm, index.htm, index.html")

Using createdSite As DirectoryEntry = newSite.Children.Add("Root", "IIsWebVirtualDir")

'12. Set Source Path
Me.SetMetabaseSingleProperty(createdSite, "Path", localPath)

'13. Create the webapplication on website root
If iisUnderNT Then
createdSite.Invoke("AppCreate", False)
createdSite.CommitChanges()
Else
createdSite.Invoke("AppCreate", 1)
createdSite.CommitChanges()
End If

'14. Assign Website Root to AppPool
Me.AssignWebsiteToAppPool(createdSite, IISDirectoryType.VirtualDirectory, appPoolName)

End Using

newSite.Invoke("SetInfo")
newSite.CommitChanges()
newSite.Close()
Else
Throw New Exception("A site can only be created in a node.")
End If

Else
Throw New Exception(String.Format("User Impersonation Failed: unable to impersonate user <{0}> for creating website", iisAdminUserName))
End If

End Using

Catch ex As Exception
ExceptionManager.Publish("Failed in CreateSite() with following exception: ", ex)
End Try

Exit Sub
End Sub

Thats it with System.DirectoryServices

SecondWay:
This is newer version and most simpler one compared to the Firstway. Add referecnce to the Microsoft.Web.Administration dll from DotNet components.


Tuesday, July 6, 2010

Huge File Uploads in ASP.NET

After a month and half, bosome time to keep this going.

There was an issue happening repeatedly, when we were trying to upload an image file with size 5MB through an File Upload Control in ASP.NET application.

Uploading a large file with File Upload Control gets tricky. The maximum default size is limited to 4MB by .NET framework, since some attackers may find this easier to upload large files which inturn consume huge server resources.

Increasing the Maximum Upload Size

The 4MB default is set in machine.config.

<system.web>
<httpRuntime executionTimeout="110" maxRequestLength="20000" />
</system.web>

But you can override it in you web.config. For example, to expand the upload limit to 20MB, you'd do this:

<system.web>
<httpRuntime executionTimeout="240" maxRequestLength="20480" />
</system.web>

Hope this solution might help to solve your problems. Please pass in your valuable feedbacks or doubts here.

Monday, May 3, 2010

Select Multiple Table Columns with JOINS

In one of our project(a kind of ETL project), there was a requirement to map the a single table columns with multiple table column. I searched in many forums and finally from MSDN learned a new implementation using Joins.

Here we go:

These are the three tables and their columns.

MasterTable:
ID
Name
Value
Area
State
County
CreatedDate
ModifiedDate

State:
ID
StateCode
State
CreatedDate
ModifiedDate

Area:
ID
AreaCode
Area
CreatedDate
ModifiedDate

The Area and State tables are like KeyValue pair tables, in which the AreaCode and StateCode represents the integer value for corresponding string values. The requirement is to create a View for MasterTable, in which the Area should be matched with AreaCode, and State to be matched with StateCode.

Code Snippet:

CREATE VIEW [dbo].[vMaster]
AS
SELECT m.ID,
m.Name,
m.Value,
a.AreaCode,
s.StateCode,
m.County,
m.CreatedDate,
m.ModifiedDate

FROM MasterTable m LEFT JOIN Area a
ON a.Area = m.Area LEFT JOIN State s
ON s.State = m.State

I think this might be useful. Don't feel shy to drop in your comments.

Happy coding. Have a good day.

Thursday, March 25, 2010

Copy Generic Collection List in DotNet

After a very long time I am learning something new. It doesn't mean that I was not experimenting new things, but I haven't learned something new in DotNet Programming for past 2 months. Quite a big time!!!!

Anyway Coming to the Collection List Addition,

I would like to explain you with the following collection object.

EG:
Product - Object which has properties (ProductID, ProductName, ProductDescription, DateSold, DaysOnMarket and e.t.c)

SoldProductList - Generic collection object of type Product
PendingProductList - Generic collection object of type Product
ActiveProductList - Generic collection object of type Product
TotalProductList - Generic collection object of type Product

The business logic is to add all the three SOLD, PENDING and ACTIVE list collections to a single collection TOTALPRODUCT list object.

Initially I had my code to loop through each items of the 3 Collection List and add it to the TotalProductList. I was very much sure there should be some other efficient way to make it. As I googled, I found a solution for it. I implemented the following and this helped me in drastically reducing my code and increased the performance of the application flow.

Code:
TotalProductList.getRange(ActiveProductList.ToArray());
TotalProductList.getRange(PendingProductList.ToArray());
TotalProductList.getRange(SoldProductList.ToArray());

Interesting Right!!! Well to fundamentally explain this, DotNet framework has as inbuilt method (getRange) for each collection to copy Array of elements of SAME TYPE. Here we are converting the ActiveProductList generic collection to an Array ( here the Array will be created of same type Product ) and then appending to TotalProductList collection which is also of same Product type.

I hope this helps you do better coding. Please let me know your thoughts and comments on this post.

Happy coding. Have a great time.

Tuesday, January 12, 2010

Importing data to SQL Server from Excel file

After a very long gap of a month and half, I had some space for me to write some technical blog.

This is all about exporting the Excel sheet to SQL Data source. You will need this in many instances to manipulate datas present in the sheet. These were the steps to be followed.

Step 1:

You have to check some basic configurations in your Surface Area Configuration of the SQL Server.

Please refer the following link to do these configurations:
http://www.kodyaz.com/articles/enable-Ad-Hoc-Distributed-Queries.aspx

Step 2:

Install Microsoft.ACE.OLEDB.12.0 component from this following link:
http://www.microsoft.com/downloads/details.aspx?FamilyID=7554F536-8C28-4598-9B72-EF94E038C891&displaylang=en


Step 3:


The DB script for importing datas from .xlsx(Excel) file to SQL Server 2005 is mentioned below.


Simple Importing:

SELECT * FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0;Database=C:\TestExcel.xlsx', 'SELECT * FROM [Sheet1$]');


Importing Data to Table:

SELECT * INTO [dbo].[ExcelTempTable] FROM OPENROWSET('Microsoft.ACE.OLEDB.12.0',
'Excel 12.0;Database=C:\TestExcel.xlsx', 'SELECT * FROM [Sheet1$]');


Note: This doesn't mean that the [ExcelTempTable] should be predefined. Its a table created dynamic with the columns from Excel sheet.


This would suffice for exporting data from .xlsx file to SQL Server. Happy coding.