|
by Naveen
11. May 2012 08:43
Download Sample Project
In previous post,
Use Facebook login in MVC, i discussed how you can use Facebook to authenticate
users in your web application. Authentication implementation will not be complete without
providing the user a way to logout out of the application. In this post I will show how to
implement Facebook logout button in your MVC application.
Facebook Logout Button or Link
If you have not tried our application running on MVC4 (Developed with VS11), try
Facebook login here Universal Shopping Mall.
Once you will login, you will see logout button appear in top right side of the page as
shown in image below.
Facebook Logout Controller and Action
Here is documentation from Facebook developer site about programmatically logging
user out of Facebook.
You can programmatically log the user our of Facebook by redirecting the user to
https://www.facebook.com/logout.php?
next=YOUR_REDIRECT_URL
&access_token=USER_ACCESS_TOKEN
The URL supplied in the next parameter must be a URL with the same base domain as your application as defined in your app's settings.
This means when we send request to Facebook to log out user, it is going to
call back on URL specified in next parameter. You will need
to implement a controller to receive this call back from Facebook. Following
snippet shows how I have set up a link for logout.
@Html.ActionLink("Logout", "Logout", "Account")
This means I have implemented an action Logout in my
Account controller. This is same controller where I added
Login action to perform login. Following code snippet shows implementation
of this Logout action in demo application.
public ActionResult Logout()
{
var fbUser = Session["fbUser"] as Models.FacebookUser;
if (null == fbUser)
{
return new RedirectResult(Request.UrlReferrer.AbsoluteUri);
}
var redirectUrl = string.Format("https://www.facebook.com/logout.php?
next={0}&access_token={1}",
Request.UrlReferrer.AbsoluteUri,
fbUser.AccessToken);
//TODO: Do book keeping about this Facebook user's activity.
FormsAuthentication.SignOut();
Session["fbUser"] = null;
return new RedirectResult(redirectUrl);
}
You will notice that I have done following things before sending logout request to
Facebook for this user.
- Called FormsAuthentication.SignOut to remove authentication cookie for this
user from the application.
-
Invalidated session variable containing this user's information. You can also
call Session.Abandon at this stage to clear all session variables.
Once request returns from Facebook, the login button appears instead of logout
button.
Demo and Sample Project
I have attached sample project with this post. You will need to replace
your Facebook application information in web.config file. And you can see this
all in action in real production application as Universal Shopping Mall.
by Naveen
10. May 2012 15:52
Download Sample Project
As Facebook IPO is coming up soon, I decided to stir some activity
around this blockbuster event. In this post I will be discuss how to authenticate
users using Facebook OAuth in your MVC application. Following screen shot shows
popular Facebook login button you may have seen at number of web sites and
applications. Yes, I am going to discuss this very button and how you will
implement authentication using Facebook.
Register your application in Facebook
Before you can begin using using Facebook for authenticating users on your web site,
you will need to register your web site as a Facebook application on Facebook
developer site. Here are the steps involved in registering your app.
Goto Facebook developer site
and login with your account.
-
You will see Apps tab at top, click on it.
-
On next screen click on Create New App button on top right side as shown
in screen shot below.
Facebook will walk you through few steps in setting up your application. After you finish
the steps, you will have the following information about your application.
There are 3 very important pieces of information on this screen that you will need to
work with OAuth authentication with Facebook.
- App ID/App Key
- App Secret
- Site URL
You can read more about their importance on Facebook site.
Display Facebook login button or link
First step is that we want to display login button our pages. I have set it up on my
shared layout in demo application. Following snippet shows how I have set it up.
@{
var fbLoginUrl = Url.RouteUrl(new { Controller = "Account", Action = "Login" });
}
@{
if (Request.IsAuthenticated)
{
var fbUser = Session["fbuser"] as MvcFaceBook.Models.FacebookUser;
<span>Welcome @fbUser.UserName</span>
}
else{
<a href="@fbLoginUrl"><img src="/content/images/facebooklogin.png" /></a>
}
}
Set up contoller for facebook login button
You can notice from code snippet above that I have set up RouteUrl to create a link that is using
Account controller with action as Login. Following code snippet shows how this controller implementation
looks like.
public class AccountController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Login()
{
// Create a token in session to save state of this request. We will use
// this to verify oAuth response from Facebook.
var requestState = new Helpers.FacebookRequestState()
{
Id = Guid.NewGuid().ToString("N"),
Url = Request.UrlReferrer.ToString(),
CreationTime = DateTime.Now
};
Session[requestState.Id] = requestState;
var redirectUrl = string.Format("http://www.facebook.com/dialog/oauth/?
client_id={0}&
redirect_uri={1}facebook/OAuth/&
state={2}",
ConfigurationManager.AppSettings["fb-applicationid"],
ConfigurationManager.AppSettings["fb-connecturl"],
requestState.Id);
var redirResult = new RedirectResult(redirectUrl);
return redirResult;
}
}
As you can see that Login action does not return any view in the application itself.
It is redirecting the login request to facebook's OAuth authentication dialog box. This is
where three pieces of information about your Facebook application get used. That information
is passed along with request URL to Facebook for verification of your request. I have
stored that information in my application in web.config file and then reading from it.
Set up MVC controller to receive response from Facebook authentication
Once user has logged into Facebook and accepted use of your application, Facebook will
send a response to URL that you have sent in redirect_uri query string
parameter. This URL has to be based on Site URL value that you have used
when registering your application. For example I have used Site URL as localhost/MvcFaceBook
for my application. And I have set redirect_uri in OAuth request to be
localhost/mvcfacebook/facebook/OAuth. Facebook will send response to this Url.
That means my application is going to need a route that can handle this request. Based on
my setting, I have created FaceBookController with a action OAuth
in it. Now my MVC application is all set to receive the response from Facebook. Following
code snippet shows how my controller looks like.
public class FaceBookController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult OAuth(string code, string state)
{
if (string.IsNullOrEmpty(code))
{ return View(); }
if (string.IsNullOrEmpty(state))
{ return View(); }
var requestState = Session[state] as Helpers.FacebookRequestState;
var fbHelper = new Helpers.FaceBookHelper();
var accessToken = fbHelper.GetFbToken(code);
var fbUser = fbHelper.GetUser(accessToken);
Session["fbuser"] = fbUser;
FormsAuthentication.SetAuthCookie(fbUser.UserName, false);
return new RedirectResult(requestState.Url);
}
}
Notice the signature of Action method. It takes two parameters, "code" and "state". Facebook
authentication service returns the handshake code in this "code" parameter. This is the code
that you return back to Facebook to get access token. Second parameter "state"
corresponds to "state" query string parameter that you can pass with authentication request.
Facebook will return that parameter as it is in response query string. You can
use that parameter for some book keeping purposes. For example I am using that parameter to
verify if the response from Facebook corresponds to one of the requests from the site and I
am saving additional information in session about that request. For example I have saved
the Url of page from where login request started. When login is complete, I am redirecting user
back to same page. You can utilize this parameter as per need of your application.
Getting Facebook user information using FaceBook SDK
Once you have successfully obtained access token from Facebook, you
can use that to request rest of the user's data from Facebook. For example I have used
Facebook C# SDK to get user's id, name and username using access token. Following
code snipper shows use of Facebook SDK.
public Models.FacebookUser GetUser(Helpers.FacebookAuthToken accessToken)
{
var fbClient = new FacebookClient(accessToken.Token);
dynamic me = fbClient.Get("me", new {fields = "id,name,username"});
Models.FacebookUser fbUser = null;
if (null != me)
{
fbUser = new Models.FacebookUser()
{
Id = Convert.ToInt64(me.id),
Name = me.name,
UserName = me.username
};
}
return fbUser;
}
Demo and Sample Project
You can see use of Facebook login in MVC application at my playground site
Universal Shopping Mall. You will
see Facebook login at top right corner. I have attached a demo project with this post
that implements all the functionality. You will have to replace the information about
your Facebook application in app settings section of web.config file.
by Naveen
7. May 2012 15:53
Download Sample Project
In previous post, how to use ajax in mvc application, I talked some basic concepts
of using ajax in mvc application. The big assumption in that discussion was that everything works
smoothly, there are not errors in execution and ajax returns response that we expected. In
reality things do not always work as planned. We have to account for unexpected conditions, errors
and other unhandled exceptions etc. In this post I will discuss following concepts related to
MVC web applications.
- Implementing custom AuthorizeFilter to extend authorization
- Handling failed ajax request on client side to display error message
Authorize Ajax request using AuthorizeAttribute
AuthorizeAttribute does not have any direct relation to discussion on handling of errors
in ajax requests. But I took the oppurunity to demonstrate how you can implement custom
filters on your controllers. Authentication and authorization are the building blocks
of secure application. It is important that you have authorize the requests coming in to
your MVC application appropriately to prevent execution of unauthorized code.
If only requirement for your application is that caller needs to be authenticated, then
you can use AuthorizeAttribute directly and there is no need for any custom implementation. But
if there is more that needs to be done and can not be handled by AuthorizeAttribute class then
you will need to implement new class that derives from AuthorizeAttribute. The following
code snippet shows class that I implemented for demo project.
public class AsyncAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// TODO: Perform authorization check here. If the call is not
// authorized, then return false. Otherwise return true
// from this method.
return base.AuthorizeCore(httpContext);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
var urlHelper = new UrlHelper(filterContext.RequestContext);
filterContext.Result = new ViewResult()
{
ViewName = "UnauthorizedAccess"
};
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
There are two important methods that can you can override to control how authorization
checks happen for method or class on which you put this attribute.
- AuthorizeCore:
This method is called to get a vote on if request is authorized or not. The base
implementation will always return false if user has not logged in. This is
the place where you can perform additional check. The method is passed the whole context
of this request in HttpContextBase parameter. If you return false from this method, your
request will send 401 status code back to caller.
- HandleUnauthorizedRequest:
If you are not looking into doing anything special if request is unauthorized then you
do not have to override this method. You can see from my implementation, I am trying
to handle unauthorized request for Ajax differently. This implementation is blocking
send of 401 error code in response and instead sending a view that has some informaiton
about the failure. Now you may be asking why not just let 401 status code goto client.
I will discuss this in more detail now.
Handling Unauthorized Ajax Request
If you send 401 status code in response to Ajax request, you will end up a view something
looking like below.
You can see that place where Ajax response was supposed to insert HTML for successful request,
you have your login page displayed there. The reason is that when authorization failed,
ASP.Net framework redirected the request to login page that was set in web.config file. This is
not what you intended. You wanted to show message to the user that he or she needs to login
if they want to execute the action on the page. This is why I have custom implementation in
HandleUnauthorizedRequest method for Ajax request. I have created a partial view in project that contains
the HTML that will be shown to user when authorization fails. Following snippet shows that
partial view.
@{
Layout = null;
}
<p>You will need to log in to this site to execute this operation!
Please click on the following link to proceed.</p>
<p>
@Html.ActionLink("Login", "Login", "Account")
</p>
Now when this authorization fails, Ajax famework the following HTML into element
specified by UpdateTargetId property value in AjaxOptions
class when you set up the request.
UpdateTargetId and OnFailure
There is one little fine print that is missing in MVC documentation. HTML element indicated
by UpdateTargetId id is only updated when Ajax request succeeds. When request fails, the
framework will not insert any error message in that HTML element. So if you want to
display some message to user or you want to know more about the error, then you will have to
implement a client side function for OnFailure event handler. In that client side
javascript code, you can extract error information from first parameter passed to the function.
Following code snippet shows how I managed to display some details about the exception thrown from
server in response to my Ajax request.
function onMessageSendFail(request, status) {
var errorDiv = $('#errorresponse');
errorDiv.html(request.responseText);
}
The detailed error message looked like below when i forced an exception from code.
Server Error in '/' Application.
--------------------------------------------------------------------------------
Operation is not valid due to the current state of the object.
Description: An unhandled exception occurred during the execution of the current web request.
Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: Operation is not valid due to
the current state of the object.
Source Error:
Line 22: public ActionResult Index(Models.ContactUsViewModel contactUs)
Line 23: {
Line 24: throw new InvalidOperationException();
Line 25: return View("ContactUsResponse", 200);
Line 26: }
Stack Trace:
Sample project attached with this post contains all the code that demonstrates all the concepts that
I discussed above.
by Naveen
6. May 2012 16:04
Download Sample Application
In this post, I will discuss some basic building blocks of using Ajax or Async mechanism in
MVC applications. I will not go into details about what is Ajax or what is Async mechanism. There are
lot of good and informative books and posts about the topic.
MVC framework helps in providing mechanism of implementing Ajax features in your web applications. When
you create a new web application, you will notice following lines in web.config file.
<appSettings>
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Notice setting of UnobtrusiveJavaScriptEnabled app setting value. This indicates to MVC
framework that your application needs to include JS support for implementing Ajax or Async mechanims. Microsoft
uses jQuery based implementation to accomplish this task.
For this discussion I have implemented a Contact Us page in web application. This page takes
3 input values from a user and then submits that information to server using Ajax. The following screenshot shows
how this page looks like in my application.
Setting up model for the page
First set up model representing the information on the page for which you want to implement Ajax. For
my application, I have created a very simple model object that contains these 3 pieces of the information.
public class ContactUsViewModel
{
public string Name { get; set; }
public string Email { get; set; }
public string Message { get; set; }
}
Create Controller for page and ajax request
This is the important part of the implementation. We will need to set up controller and
action that will be executed when client sends ajax request to server. And then server
send appropriate response for client to render. I have created a ContactUsController
for my page that serves default view for GET request and serves a different view after
getting ajax request from client. Following snippet shows my simple set up. In your real application
there will be more implementation when server receives data. This prototype shows how this all
will be set up.
public class ContactUsController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Models.ContactUsViewModel contactUs)
{
return View("ContactUsResponse", 200);
}
}
Setting up Html form for Ajax in Mvc
Next step is to create views that we are going to server when user loads the page and
then sends message.
@model MvcAsyncForms.Models.ContactUsViewModel
@{
ViewBag.Title = "Contact Us";
AjaxOptions ajaxOptions = new AjaxOptions()
{
UpdateTargetId = "messageresponse",
Url = Url.Action("Index"),
LoadingElementId = "sendingmessage",
LoadingElementDuration = 3000,
OnComplete = "onMessageSent"
};
}
<div id="sendingmessage">
<p>Sending your message .....</p>
</div>
<div id="messageresponse"></div>
<div id="contactUsForm">
<h2>Contact Us</h2>
@using (Ajax.BeginForm(ajaxOptions))
{
<table>
<tr>
<td><span>Name:</span></td>
<td>@Html.EditorFor(m => Model.Name)</td>
</tr>
<tr>
<td><span>Email:</span></td>
<td>@Html.EditorFor(m => Model.Email)</td>
</tr>
<tr>
<td colspan="2"><span>Message:</span></td>
</tr>
<tr>
<td colspan="2">
@Html.TextAreaFor(m => Model.Message)
</td>
</tr>
<tr>
<td colspan="2">
<div style="text-align: center">
<input type="submit" value="Send Message" />
</div>
</td>
</tr>
</table>
}
</div>
<script type="text/ecmascript">
function onMessageSent() {
$('#contactUsForm').hide();
}
</script>
There are two pieces in this view implementation. First you will need to set up AjaxOptions
object that specifies all the ajax related options. You can see that we have set up following properties
to indicate how we want to execute ajax request and how response will be rendered.
- Url: This property sets up the POST url where requests will be sent
- UpdateTargetId: This is HTML element that will be updated with response sent by server after processing ajax request
- LoadingElementId: This is the HTML element that will be shown to user while ajax request is being executed and user is waiting
for request to complete. This where you can show some message or some animation to indicate to the user that
execution is in progress. This is a good practice that you should keep the users aware of progress of
their request.
- OnComplete: This is client side event triggers that when ajax request is completed. There are four events that are triggered
for ajax request, OnBegin, OnComplete, OnSuccess and OnFailure. These allow you to
handle various stages of ajax request so you can take action on client side accordingly. For demo
purposes I have only handled OnComplete event where I am hiding request form after ajax request is
complete.
There are more options that you can set in AjaxOptions class. I will discuss more advanced settings in
subsequent posts. For this discussion I have only set most basic ones to get the job done.
Ajax.BeginForm
This is the place where you set up HTML form that will be used to send the data to server
to execute your ajax request. There are about 12 overloads available for this method. I have used the most basic
one that takes AjaxOptions as parameter to set up the request. In this block you will set up all the
client side form that contains the data to be submitted to server.
Response for Ajax request
MVC framework makes it very easy for us to send us well formatted HTML response for any ajax request.
And then it uses element represented by UpdateTargetId in AjaxOptions to display the response
on client side. I have implemented a partial view that is sent back to client when ajax request
is complete.
@model int
@{
Layout = null;
}
@if (Model == 200)
{
<span style="color: #00ff21; font-size: 1.2em;">Your message has been sent!</span>
}
else
{
<span style="color: #f00;font-size: 1.2em">Your message could not be sent!</span>
}
<p>
@Html.ActionLink("Home", "Index", "ContactUs")
</p>
You can see how easy it is to implement Ajax in MVC web applications. In subsequent posts I will
discuss more advanced details about the use of Ajax in MVC applcations.
Demo and sample code
You can see this in action at UniversalShoppingMall
site that has been created using MVC4 with VS11. You can click on Contact Us link in top
navigation and see how the ajax request works. The demo project included in this post
is a simple stand alone implementation of this contact page.
by Naveen
4. May 2012 16:00
searching, displaying lists of results and paging through them is one of the most common tasks we
perform in web applications. In ASP.Net when you use controls like GridView, ListView etc. along
with viewstate, things are little straight forward. But when you use are using stateless mechanism
with MVC framework, then things are little different.
In this post I will show I implemented paging in MVC4 application and preserved search query
in routing urls so that when a user is clicking on pager, the search query gets passed
along. For demo purposes I have built a shopping mall using Amazon's product advertising
web service as product store.
I will start with showing the razor syntax for pager on my page.
<div class="pager">
@Html.PageLinks(Model.PagingInfo, Model.QueryParameters.Keywords,
x => Url.Action("List",
new {page=x, category=Model.Category.Name, keyword=Model.QueryParameters.Keywords}))
</div>
I have implemented an extension method PageLinks that is used to generate
HTML for pager. The key part of this implementation is the last parameter to this method where
I am passing product category name along with the search query string. Lets see how the method
signature looks like.
public static MvcHtmlString PageLinks(this HtmlHelper html,
PagingInfo pagingInfo, string query, Func<int, string> pageUrl)
{...}
This methos is responsible for returning HTML string. Now let me some code from this function
that builds these paging links.
for (int i = start; i <= end; i++)
{
tag = new TagBuilder("a");
tag.MergeAttribute("href", pageUrl(i));
tag.InnerHtml = i.ToString();
if (i == pagingInfo.CurrentPage)
{
tag.AddCssClass("selected");
}
pagingLinks.Append(tag.ToString());
}
The following image shows the pager looks like on the web site.
Generated HTML for pager
<div class="pager">
<span>Page:</span><a class="selected" href="/Electronics?keyword=iphone">1</a>
<a href="/Electronics/Page2?keyword=iphone">2</a>
<a href="/Electronics/Page3?keyword=iphone">3</a>
......
</div>
You can see that the pager URL contains the information about page number and search string is contained
in the query string. Now lets see how the route looks like along with controller signature
that routes the click on these links correctly.
routes.MapRoute(
null, "", new { Controller = "Product", action = "List",
category = (string)null, keyword = (string)null,
page = 1 });
routes.MapRoute(
null, "Page{page}", new { Controller = "Product", action = "List",
category = (string)null, keyword = (string)null },
new { page = @"\d+" });
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult List(string category, string keyword, int page = 1)
{....}
It is very important that you set up your routes correctly when you are implementing paging
with more information than just page index and search query terms.
Demo Application
You can see all this in action at UniversalShoppingmall. You
can play around by putting some search term in text box and playing with paging control to see
how the URL in pager changes and how the URL looks like in browser.
by Naveen
28. April 2012 07:53
When using dependency injection, some time we need to pass additional parameters in constructor of that object. Ninject provides a very handy method that you can use to pass arguments when you bind the interfaces. I have a similar situation in my shopping web site. I uses MVC framework. It has an interface for repository component of the web site. One of the repository used in the application is
Amazon web service. Each amazon web service needs to be associated with some identity parameters. The class that implements repository for amazon web service requires that caller passes identity parameters. You could argue that why this parameter is not a dependency as well so I could use binding for it. The problem is that it is hard to come up with a unified identity interface for each type of b2b web services. Therefore it made sense that each repository will handle this identity parameters on its own.
The following code shows how WithConstructorArgument method is used to pass parameters to constructor when
Ninject creates instance of the object.
private void AddBindings()
{
RequestIdentity identity = new RequestIdentity()
{
AssociateTag = ConfigurationManager.AppSettings["awsassociatetag"],
AccessKey = ConfigurationManager.AppSettings["awsaccesskey"],
SecretKey = ConfigurationManager.AppSettings["awssecretkey"]
};
NinjectKernel.Bind<IProductsRepository>().
To<ProductsRepository>().
WithConstructorArgument("identity", identity);
}
Following code shows ProductRepository class implementation that is expecting the parameter to be passed to it.
public class ProductsRepository : IProductsRepository
{
private RequestIdentity Identity { get; set; }
public ProductsRepository(RequestIdentity identity)
{
if (null == identity)
{
throw new ArgumentNullException("identity");
}
Identity = identity;
}
}
by Naveen
25. April 2012 15:34
While working on my MVC4 web application using VS11, I ran into the following error. I have an extension method that was to be called from razor page.
Compiler Error Message: CS1061: 'System.Web.Mvc.HtmlHelper<ByteBlocks.ShoppingMall.Models.ProductListViewModel>' does not contain a definition for 'PageLinks' and no extension method 'PageLinks' accepting a first argument of type 'System.Web.Mvc.HtmlHelper<ByteBlocks.ShoppingMall.Models.ProductListViewModel>' could be found (are you missing a using directive or an assembly reference?)
The error itself is self explanatory that application is not able to locate the extension method. This means that the namespace that
contained the extension method needs to be included on the page. There are two ways you can accomplish this. First is by adding the
namespace in web.config file in page > namesapces section as shown below. This web.config file is the one that you have under Views folder, not the one in root folder of application.
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory,
System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="ByteBlocks.ShoppingMall.Helpers" />
</namespaces>
</pages>
</system.web.webPages.razor>
Second way to include namespace is by adding @using directive at the top of your razor page as shown below.
@using ByteBlocks.ShoppingMall.Helpers
by Naveen
3. April 2012 15:13
In previous post MVC4 Web Application
projects in VS11 I touched upon how you can use VS11 to create MVC4 web applications. In this project I will discuss
little about setting up view and mainly a very nice concept introduced with ASP.Net, Master Pages.
We have all used Master Pages in ASP.Net to put together common rendering tasks across all pages into one
common page. In MVC4 this concept is carried on. There is only one change in MVC4. There is no term as
Master Page. MVC4 refer to master page as Layout. If you look at the structure of the project
files created by VS11, you will notice file named _Layout.cshtml. This is master page or
layout for your MVC4 web application. Following snippet shows how it looks in my sample project.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl
("~/Content/css")" rel="stylesheet" type="text/css" />
<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl
("~/Content/themes/base/css")" rel="stylesheet" type="text/css" />
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl
("~/Scripts/js")"></script>
</head>
<body>
<header>
<div style="background-color: #f77b34;color: #ffffff;">
<a href="Home">Home</a>
</div>
</header>
@RenderBody()
<footer>
Copyright © ByteBlocks.com
</footer>
</body>
</html>
Looks very familiar to what you are used to seeing in master page of ASP.Net applications. I will explain
more about Layout in MVC4.
_ViewStart.cshtml and _Layout.cshtml
You must be asking how does MVC framework know what layout file to use and what other files are there
in Views folder in your project. MVC framework look for _Viewstart.cshtml file in
Shared folder in your installation. This is the file that contains directives for which layout file to
use. Following snippet shows how it looks in sample application.
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
As you can see that _Viewstart.cshtml has one line that sets Layout property to location of
file that is to be used for master layout of the pages. This is how MVC framework knows about
master page of your mvc application. If you set this property to null, this means
that you do not want to use any master page or layout for your view. If you look inside
Error.cshtml file in your project, you will notice following lines at the top of the
file directing the framework that it does not want to use any layout for the page.
@{
Layout = null;
}
RenderBody
Now you are asking how does MVC framework know where to include content of individual views inside
layout. If you look at code snippet at top of this post, you will notice that we are calling
RenderBody method. This is the method that is responsible for rendering
individual views and including their content in layout.
Above image shows how i used layout to display common content and individual view content on the page.
The top menu and footer was put in Layout file. The welcome message was put in Home > Index
view.
This is simple explanation of how concept of master pages in MVC is implemented. In subsequent posts
i will use MVC term for master page and that is Layout.
by Naveen
31. March 2012 09:28
This month I have written few posts on some upcoming new features of ASP.Net 4.5 which are going
to be released with VS2011. In this post I am going to start a series on MVC 4
which is part of VS11 Beta release. MVC4 is still in beta phase but it is part of VS11 at the moment.
In this post I will focus on very basic steps on how to create a simple MVC4 project using VS11. In subsequent
posts I will discuss more details about MVC4 and what is new in MVC4 as compared to previous
versions of MVC framework.
How to create MVC 4 project
Start VS11 and select File > New > Project menu option. It will bring up following
dialog box. Select language that you would like to use and then select ASP.Net MVC 4 Web Application.
After you pick project type as MVC 4 Web Application, you will be prompted to pick a template for your
web application. There are some per-defined templates available in VS11 that will create lot of
required infrastructure for your application. I am going to focus the discussion around the fact that we
are learning MVC 4 from scratch and would like to know how the technology works. So I will pick
Empty as my project template. You will notice that VS11 has created minimal files in the
project. Since Razor is rendering engine of choice, I will keep that selected when you pick your project
template.
Add controller in MVC 4 application
As I mentioned above that I have picked Empty project template. So if you will run the
application, you will end up with some web server related error saying resources not found etc. This means
that we do not have any page in the application to display to the user. In MVC it is all done through use
of controllers. When a request comes into the web application, it is routed based on the controllers that
are mapped to parse incoming URLs and translate them into appropriate views. So first thing we will do is to
add a new controller. You will notice that you have an empty folder named Controller in
your project. MVC looks for controller definitions in that folder bt default. And the default
controller it looks for is HomeController. Right click on Controller folder
and choose Add > Controller menu option. Name the controller as HomeController
and leave the template drop down selection to Empty controller. We will build up on this as we
go along.
You will notice that now you have your first controller added to your project as shown below.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
As you can see very plain and simple code that just returns an instance of View
Add view in MVC 4 application
If you will run the application, you will again get errors saying that there is no view associated. If you
look at the code above, you can see an instance of View is being returned but we have no view
associated with our controller. Right click on Index method or anywhere inside Index
method and notice a menu option Add view. Click on it and you will notice the name of the view
is set to Index. For now just leave all the default options selected and click OK and you will notice
that you have a new entry under Views folder in your project. This correspnds to Index
view that you just added. Open Index.cshtml file and you will find starter Razor mark up added to it. I modified
it to look as below.
@{
ViewBag.Title = "ByteBlocks.com";
}
<h2>Welcome to ByteBlocks.com Mvc4 Tutorials</h2>
I will discuss all this Razor syntax and what all this means in next post. For now you can see that how quick
it is to create a simple MVC 4 project in VS11 and get it up and running.
by Naveen
28. March 2012 08:43
This week I was evaluating a help desk application to use for our site. One of the key factors
in decision making was ability to connect to application's API using some form of web service. It turns
out that this application supported REST API. First thing I needed to look for was how do I authenticate
request to extract data. This application uses BASIC authetication. That would not be
my first preference to use any application that uses BASIC authentication because of concerns related to
user credentials being exposed in clear text in request. In this post I will discuss how to submit
a HTTP request with Basic Authentication.
Basic Authentication Protocol
Basic authentication protocol manadates that HTTP request should include
Authorization header that contains user credentials in the following format.
Authorization = Basic UserCredentials
where
UserCrdentials = Base64 encoded value of Login":"Password string
Now you can see why this mechanism is not safe because credentials are exposed in the header
directly and it does not take any effort to decode this Base64 encoded pair. Thats the besides the point
for this discussion.
Basic Authentication With .Net
Here is code snippet from my evaluation application. There is nothing fancy in this code. The code that
relates to authentication has been highlighted.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Web;
namespace FreshdeskConsole
{
class Program
{
const string BaseUrl = "https://{0}.freshdesk.com/";
const string CompanyName = "byteblocks";
const string LoginUrl = "login";
const string TicketsUrl = "helpdesk/tickets.xml";
const string LoginEmail = "xyz@byteblocks.com";
const string Password = "mypassword";
static void Main(string[] args)
{
GetAllTickets();
}
static void GetAllTickets()
{
var baseUrl = string.Format(BaseUrl, CompanyName);
var ticketsUrl = string.Format("{0}{1}", baseUrl, TicketsUrl);
var webReq = WebRequest.Create(ticketsUrl);
var credentialsCache = new CredentialCache();
credentialsCache.Add(new Uri(baseUrl), "Basic", GetUserCredentials());
webReq.Credentials = credentialsCache;
webReq.Headers.Add("Authorization", GetBasicAuthenticationData());
webReq.Method = "GET";
webReq.PreAuthenticate = true;
webReq.ContentType = "application/x-www-form-urlencoded";
var response = webReq.GetResponse();
ProcessWebResponse(response);
}
static void ProcessWebResponse(WebResponse response)
{
}
static NetworkCredential GetUserCredentials()
{
var credentials = new NetworkCredential(LoginEmail, Password);
return credentials;
}
static string GetBasicAuthenticationData()
{
var authInfo = string.Format("{0}:{1}", LoginEmail, Password);
var bytes = new UTF8Encoding().GetBytes(authInfo);
var encodedInfo = Convert.ToBase64String(bytes);
return string.Format("Basic {0}", encodedInfo);
}
}
}
NetworkCredentials and CredentialsCache
.Net framework exposes NetworkCredentials and CredentialsCache classes
that you can use to set a user's credentials to attach to a web request. You can from the code above how
this is done.
Authorization Header
This is something that I found out after spending couple of hours on trying to figure out why
credentials were not being sent to web service. Although I had set CredentialsCache to WebRequest,
the information was not being sent to server. So I had to go back to basics and do it old fashioned
way of explicitly setting Authorization header.
If you have any questions about Basic authentication use in .Net, feel free to post a comment in this post
and I will try to get back to you as soon as I can.
|
|