Monday, May 2, 2011

RESTful Services With WCF in Asp.Net

What is REST
REST stands for Representational State Transfer. (It is sometimes spelled "ReST".) It relies on a stateless, client-server, cacheable communications protocol -- and in virtually all cases, the HTTP protocol is used.
REST is an architecture style for designing networked applications. The idea is that, rather than using complex mechanisms such as CORBA, RPC or SOAP to connect between machines, simple HTTP is used to make calls between machines.
  • In many ways, the World Wide Web itself, based on HTTP, can be viewed as a REST-based architecture.
RESTful applications use HTTP requests to post data (create and/or update), read data (e.g., make queries), and delete data. Thus, REST uses HTTP for all four CRUD (Create/Read/Update/Delete) operations.
Sample REST Application using WCF
WCF is the Microsoft framework for building applications that communicate over network using different protocols. WCF allows the developers to build distributed applications using SOAP. WCF also had the ability to expose and consume REST services.This post explains how to build REST service using WCF.
Create a new WCF Service in VS 2010 as follows,here select Web Location as Http.

Add the RestService.Svc  file to the solution Explorer .
When you add RestService.svc it will automatically adds IRestService.cs and RestService.cs files to your Solution Explorer

Add following methods in IRestService.cs File

[ServiceContract]
public interface IRestService
{
    [OperationContract]
   string HelloWorld();
    [OperationContract]
    string HelloWorldWithParameter(string input);
}

Add folowing NameSpaces and methods to the RestService Class

using System.ServiceModel.Web;
using System.ServiceModel.Activation;
[ServiceContract]
public class RestService
{
    [OperationContract]
    [WebGet(UriTemplate = "/Hello", ResponseFormat = WebMessageFormat.Xml)]
    string HelloWorld()
    {
        return "Welcome to My First Rest Service";
    }
   
    [OperationContract]
    [WebGet(UriTemplate = "/Hello/{input}", ResponseFormat = WebMessageFormat.Xml)]
    string HelloWorldWithParameter(string input)
    {
        return input;
    }
      
}

Here we can add WebFGet and WebInvoke attributes to the Methods and we can add WebMessage format as Json or Xml

WebGet
The WebGet attribute exposes operations using the GET verb. The GET has significant advantages over other HTTP verbs. First, the endpoint is directly accessible via a Web browser by typing the URI to the service into the address bar. Parameters can be sent within the URI either as query string parameters or embedded in the URI. Second, clients and other downstream systems such as proxy servers can easily cache resources based on the cache policy for the service. Because of the caching capability, the WebGet attribute should be used only for retrieval.
WebInvoke
The WebInvoke attribute exposes services using other HTTP verbs such as POST, PUT, and DELETE. The default is to use POST, but it can be changed by setting the Method property of the attribute. These operations are meant to modify resources; therefore, the WebInvoke attribute is used to make modifications to resources.


 Add the service host declaration with the following attributes

End Point Configuration in Web.config file
<system.serviceModel>
    <services>
      <service name="MyFirstRestWCFService.RestService" behaviorConfiguration="HttpGetMetadata">
        <endpoint address=""
                  binding="basicHttpBinding"
                  contract="MyFirstRestWCFService.IRestService" ></endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HttpGetMetadata">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>


Now Enter this URL in your browser the output will display in XML format,because we have used WebMessage Format as Xml.
How to Consume REST-WCFServices
You can take advantage of the System.Net classes to programmatically issue HTTP requests and process the responses. The following code illustrates how easy this can be by using the HttpWebRequest and HttpWebResponse classes:
string uri = "http://localhost/MyFirstRestWCFService/RestService.svc/Hello";
            HttpWebRequest req = WebRequest.Create(uri) as HttpWebRequest;
            HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
            Stream stream = resp.GetResponseStream();
            StreamReader reader = new StreamReader( stream );
            string text = reader.ReadToEnd();

Conclusion

Now We have learned how to Develop and consume REST Services using WCF.

How to Integrate Google Authentication in Asp.Net Application

Hi here I am going to discuss how to integrate Google authentication in our local asp.net Application.
Recently I got the requirement to integrate Google authentication with asp.net application which is build using asp.net membership concept. My main aim is to use Google authentication in my application because now a days as everybody knows security is crucial for our applications. So I decided to use Google authentication in my application.
Google providing Authentication services for web application
As Google documented The OAuth authorization process involves a series of interactions between your web application, Google's authorization servers, and the end user.
At a basic level, the process is as follows:
  1. Your application requests access and gets an unauthorized request token from Google's authorization server.
  2. Google asks the user to grant you access to the required data.
  3. Your application gets an authorized request token from the authorization server.
  4. You exchange the authorized request token for an access token.
  5. You use the access token to request data from Google's service access servers.
When your application initially requests access to a user's data, Google issues an unauthorized request token to your application.
When user requests for local application URL http://localhost:50034/Login.aspx

If the user is not already logged in, Google prompts the user to log in page.

Google then displays an authorization page that allows the user to see what Google service data your application is requesting access to

If the user approves your application's access request, Google issues an authorized request token. Each request token is valid for only one hour. Only an authorized request token can be exchanged for an access token, and this exchange can be done only once per authorized request token.
By default, access tokens are long-lived. Each access token is specific to the user account specified in the original request for authorization, and grants access only to the services specified in that request. Your application should store the access token securely, because it's required for all access to a user's data.
We have mainly two methods to access Google authentication in to our application
1. Request for token
2. Handles the token
private string realm = null;
private string provider = "Google";
protected void Page_Load(object sender, EventArgs e)
        {
            realm = Request.Url.Scheme + "://" + Request.Url.DnsSafeHost + ":" + Request.Url.Port + Request.ApplicationPath;

            if (!IsPostBack)
            {
                if (!String.IsNullOrEmpty(Request.PathInfo))
                {
                    if (Request.PathInfo.StartsWith("/requestToken"))
                        MakeRequestForToken();
                    else if (Request.PathInfo.StartsWith("/authorizeToken"))
                        HandleAuthorizeTokenResponse();
                }
            }
        }

        /// <summary>
        /// Step 1: Get a Request Token
        /// </summary>
        private void MakeRequestForToken()
        {
            string consumerKey = "anonymous";
            string consumerSecret = "anonymous";
            // Google requires an additional "scope" parameter that identifies one of    the google applications
            string requestTokenEndpoint = "https://www.google.com/accounts/OAuthGetRequestToken?scope=https://www.googleapis.com/auth/userinfo#email";
            string requestTokenCallback = GetRouteableUrlFromRelativeUrl("GoogleAuth/oAuth/GoogleValidation.aspx/authorizeToken/google/");
            string authorizeTokenUrl = "https://www.google.com/accounts/OAuthAuthorizeToken";

            // Step 1: Make the call to request a token
            var oAuthConsumer = new OAuthConsumer();
            var requestToken = oAuthConsumer.GetOAuthRequestToken(requestTokenEndpoint,   realm, consumerKey, consumerSecret, requestTokenCallback);
            PersistRequestToken(requestToken);

            // Step 2: Make a the call to authorize the request token
            Response.Redirect(authorizeTokenUrl + "?oauth_token=" + requestToken.Token);
        }

        private void HandleAuthorizeTokenResponse()
        {
            string consumerKey = "anonymous";
            string consumerSecret = "anonymous";
            string token = Request.QueryString["oauth_token"];
            string verifier = Request.QueryString["oauth_verifier"];
            string accessTokenEndpoint = "https://www.google.com/accounts/OAuthGetAccessToken";

            // Exchange the Request Token for an Access Token
            var oAuthConsumer = new OAuthConsumer();

            var accessToken = oAuthConsumer.GetOAuthAccessToken(accessTokenEndpoint, realm, consumerKey, consumerSecret, token, verifier, GetRequesttoken().TokenSecret);

            // Google Only - This method will get the email of the authenticated user
            var responseText = oAuthConsumer.GetUserInfo("https://www.googleapis.com/userinfo/email", realm, consumerKey, consumerSecret, accessToken.Token, accessToken.TokenSecret);

            string queryString = responseText;
            NameValueCollection nvc = StringToNameValueCollection(responseText);

            if (nvc["email"] != "")
            {
                string userName = "";
                string password = "";
                userName = Membership.GetUserNameByEmail(nvc["email"].ToString());
                password = Membership.Provider.GetPassword(userName, String.Empty);
                FormsAuthentication.RedirectFromLoginPage(userName, false);
            }
        }

In above method I am getting Email of the authorised person by Google and I am checking with my database for email existence, if he is existed in my database i will give him permission to access my application.
Web.cofig file Settings
<configuration>
  <connectionStrings>
    <add name="Connection" connectionString="Data Source=RD780-RANDDMC;Integrated Security=true;Initial Catalog=Sample" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <system.web>
    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider"
             type="System.Web.Security.SqlMembershipProvider"
             connectionStringName="Connection"
             applicationName="sampleapplication"
             enablePasswordRetrieval="true"
             enablePasswordReset="true"
             requiresQuestionAndAnswer="false"
             requiresUniqueEmail="true"
             passwordFormat="Encrypted"
             maxInvalidPasswordAttempts="5"
             minRequiredPasswordLength="4"
             minRequiredNonalphanumericCharacters="0"
             passwordAttemptWindow="10"
             passwordStrengthRegularExpression="^(?=.*\d).{4,8}$"
           />
      </providers>
    </membership>
    <authentication mode="Forms">
      <forms name=".ASPXFORMSDEMO" loginUrl="~/Login.aspx"/>
    </authentication>
    <authorization>
      <allow users = "*" />
      <deny users ="?" />
    </authorization>
    <profile>
      <providers>
        <clear/>
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="Connection" applicationName="SampleApplication"/>
      </providers>
    </profile>
    <roleManager enabled="false">
      <providers>
        <clear/>
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="Connection" applicationName="SampleApplication"/>
      </providers>
    </roleManager>
    <machineKey validationKey= "836B8961579E88E2BE1819C1176518A6BECCD1670B783C62E8C4E16B2A5637EAFA0C743E8A0B81A6BF25A5539F2EE716948BFFD3B980FFF26533F8CAD71C9767"
decryptionKey="B3AFD7D4C4C1513E06403664B1DA7FEC7E0D225B23B3FD83DE99B9A75708352C" validation="SHA1" decryption="AES"/>
    <compilation debug="true" targetFramework="4.0"/>
  </system.web>
</configuration>

Here I am proving sample. Please download and try to use Google authentication in your asp.net application.
Note: when running this application you may get the following error while retrieving passwords from asp.net membership user.
You must specify a non-autogenerated machine key to store passwords in the encrypted format. Either specify a different passwordFormat, or change the machineKey configuration to use a non-autogenerated decryption key.
Please refer this link to resoleve the above issue
References

Sunday, May 1, 2011

How to use joins and orderby in Linq to Sql


LINQ to SQL is designed to support ordering by simple primitive types, such as string, int,datetime and so on, for this example I have taken Orders and Customers tables in Northwind Database.
DataClasses1DataContext context = new DataClasses1DataContext();
            var Details = from cus in context.Customers
                          join ord in context.Orders on cus.CustomerID equals ord.CustomerID
                          orderby ord.OrderDate descending
                          select new
                          {
                              cus.Address,
                              cus.City,
                              cus.CompanyName,
                              cus.ContactName,
                              ord.OrderDate,
                              ord.ShipAddress,
                              ord.ShipVia
                          };