|
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
26. April 2012 06:15
In my previous post
Authentication and Dynamic content in MVC using Model Binding I described how you can bind your model to
input controls and then binding will transport the values back and forth between client and server. In this
post I will extend this concept and show how to pass some additional parameters with FORM's post action along
with the data that will be passed with model binding.
One of the common activities in an application is to perform search. For that we get input from user in text box
,some drop down or some other form of control. Then that information is passed back to server to perform
search on some repository and return results to the user. In the sample project, I am trying to add a search
box on my product listing page.
Model Binding With Text Box
To take advantage of model binding, I have bound my view to a ViewModel class in my application. One
of the objects in this view model is QueryParameters which contains a property named Keywords.
So in my FORM rendering, I have bound the text box to this property. Based on this approach the code
looks like as below.
Razor View Code
@model ByteBlocks.ShoppingMall.Models.ProductListViewModel
@{
ViewBag.Title = "Products";
}
@using (Html.BeginForm("Search", "Product"))
{
@Html.EditorFor(m => m.QueryParameters.Keywords);
<input type="submit" value="Search" />
}
Controller Code
[HttpPost]
public ViewResult Search(ProductListViewModel model)
{
return View();
}
This works like a champ. If I was not interested in filtering the search based on any other
existing criteria, this will fly. But if you look at the image above, you will notice that
on left side there is a navigation bar that has product categories. So if a user is interested
in searching for some item in certain category, then I will have to let my Search action
know about that as well. This means FORM's post action will need to carry more data. There are few approaches
you could take.
- We can take advantage of model binding by adding a new property, Category, to QueryParameter
and then add a hidden field to form which will bind to this property.
-
Second approach would be to take advantage of Html.BeginForm method's overload
and pass additional parameters to FORM's post data. Since I already have route that
knows about product category, I can get the value of this route parameter using
ViewContext and pass it back and forth. I like this approach because now I don't
have to extend my view model object for something that may or may not be required. In this particular
case product category was going to be part of the view model so it was perfect to take advantage
of model binding. But there will be cases where you could take advantage of FORM's post data
package itself and pass the data to server.
Based on the second approach the code changes as below.
Razor View Code
@using (Html.BeginForm("Search", "Product",
new { category = ViewContext.RouteData.Values["category"] }))
{
@Html.EditorFor(m => m.QueryParameters.Keywords);
<input type="submit" value="Search" />
}
Rendered Html
<div id="Div2">
<form action="/Product/Search?category=Apparel" method="post">
<input class="text-box single-line" type="text" value="" />
<input type="submit" value="Search" />
</form></div>
Controller Code
[HttpPost]
public ViewResult Search(string category, ProductListViewModel model)
{
return View();
}
Notice how rendered HTML has appended category as query string parameter to form's action URL. And
Mvc framework passes that as parameter with same name in controller's action method.
View content of ViewContext
You can view content of ViewContext object in your page at any time by setting a break point
in Razor view itself. Then in debugger's immediate window you can type ViewContext and go
from there. Following snippet shows how I looked at contents of ViewContext object in my
application.
ViewContext.RouteData.Values.Keys
Count = 4
[0]: "Controller"
[1]: "action"
[2]: "category"
[3]: "page"
ViewContext.RouteData.Values["category"]
"Apparel"
In subsequent posts I will discuss some more tips and tricks related to Mvc4 using VS11.
6a8bffa9-3fc8-4126-a189-cc56d296fc20|0|.0
Views: 358
Tags: MVC, ASP.Net
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
22. April 2012 15:01
Download Sample Application
Recently I was working on a prototype for implementation of logging mechanism for
my application. Previously I used to use Unity for
Dependency Injection (DI) to inject different logging frameworks into the
application for integration and unit testing. Now I am switching to using
Ninject for DI. In this post I will how you can to use
Ninject in your applications. I will not go into details why I chose
Ninject and not Unity for future projects. That will be topic for discussion for
another day. For now I will summarize it in one line that Ninject is light weight and
easy to use framework as compared to Unity.
Download Ninject Framework
You can download Ninject from Codeplex.
Or better option is to get it using NuGet manager. Add reference to Ninject.dll
in your project.
Create Interface and Classes for DI
For my logger, I created interface IAppLogger that will act as interface for all
logging methods for my application. Following snippet shows sample of this interface.
public interface IAppLogger
{
void Log(..............);
void Log(..............);
}
Following code snippet shows sample of concrete class implementation for this interface. This
class implements logging mechanism using Log4Net.
public class Log4NetLogger : IAppLogger
{
private static readonly ILog MyLog = LogManager.GetLogger(typeof(Log4NetLogger));
public Log4NetLogger()
{
BasicConfigurator.Configure();
}
public void Log(string id, string context, string methodName,
string methodParams, string value)
{
MyLog.Info("Start");
MyLog.Error(string.Format("{0} {1} {2} {3} {4}",
id, context, methodName, methodParams, value));
MyLog.Info("End");
}
public void Log(string id, string context, string methodName, Exception ex)
{
MyLog.Info("Start");
MyLog.Fatal(context, ex);
MyLog.Info("End");
}
}
Now that we have interface and class set up to include in DI, we can now look at how
Ninject makes it easy to implement DI.
Implement Ninject Module
First step in using Ninject is to bind interface to object that will need to be
created when application encounters DI. Create a class that derives from NinjectModule.
Override Load method to include bindings. In this sample I will just use a simple
implementation of Bind method. There are more advanced overloaded methods available to
control the binding in more controlled way. For this sample, the following simple
implementation will work.
public class LoggerModule : NinjectModule
{
public override void Load()
{
Bind<IAppLogger>().To<Log4NetLogger>().InSingletonScope();
}
}
What this code means is that every time there is an instance of IAppLogger to be injected
into the application, create an instance of Log4NetLogger class. Since we need singleton
instance for logger, we call InSingletonScope method that indicates to Ninject
to create singleton Log4NetLogger class.
You can include all bindings of your application in one module. But it is preferred that
you create multiple modules and include binding related to certain sections of the application
into appropriate modules.
Add NinjectModules into framework
Now that we have implemented our NinjectModule we need a way to tell Ninject framework
about this. You can add one more modules into IKernel object of Ninject. Following
method show how DI framework gets to know about our modules.
static void SetupDI()
{
NinjectKernel = new StandardKernel(new LoggerModule());
}
Add DI to class using Inject attribute
Now we have DI framework set up for our logger interface. Lets see how we are going to
use DI in our classes. In this sample, I have create AmazonRepositary
class. I would like to inject IAppLogger object into this class so I can log any errors
or information into my logger. Following code snippet shows how I used Inject
attribute to insert IAppLogger to class. In this case I am using Constructor Injection
pattern.
public class AmazonRepository
{
private IAppLogger _appLogger;
[Inject]
public AmazonRepository(IAppLogger appLogger)
{
_appLogger = appLogger;
}
public void GetProducts(SearchParameters searchParams, string ip)
{
.....
}
}
Inject attribute lets Ninject framework know that when Ninject kernel is used to
create an instance of AmazonRepository object, it will create an instance of
IAppLogger object and inject that into class constructor. Following code shows how
kernel object is used to create this class.
var repo = NinjectKernel.Get<AmazonRepository>();
You can see that your implementation does not need to know what logger class is going to
be used when creating instance of injected interface. You have already set up the
binding in NinjectModule. By writing few lines of code we have managed to use Ninject
as our DI framework. In subsequent posts, I will discuss other DI patterns and some
advanced use of binding mechanisms.
Sample Code
I have attached sample project with this post that I used for demonstrate use of
constructor patterns for DI. This project was created using VS11 and .Net 4.5. There is
nothing specific to .Net4.5 used in this implementation. You should just be able to use the
same code in VS2010.
c8c4d00e-be82-4c24-93e7-92dda0913a49|0|.0
Views: 238
Tags: DI, Ninject
.Net
by Naveen
21. April 2012 17:29
In this post I will discuss where you will find Recycle Bin in Windows 8 and to take action on items in
recycle bin. The topic seems kind of simple, but when you start using Windows 8 and Metro UI, there are some old features
that will never get old and cleaning up disk on your machine is one of the ones.
When you start Windows 8, you have Metro UI up and running. To access Recycle Bin you will need to switch
to Desktop. There are two ways you can do it. You can use Desktop title from Metro UI or you can hit
Start/Windows button on your keyboard. This will bring you to classic desktop ui mode. Here you will see familiar Recycle Bin
icon at top left location. Double click on it and bring up your dialog box for recycle bin.
You will notice that the top menu part of this dialog box looks little different than what you are used to seeing
prior to Windows 8. You may wonder what happened to buttons like Restore or Empty Recycle Bin. They are still there but
you need one more click now. Notice there is Recycle Bin Tools button. And under that there is Manage button. Clicking on
it will bring up ribbon that has the buttons that you were looking for.

d367c4df-62bc-435a-9e32-47bcda86163e|0|.0
Views: 179
Tags: Windows 8
|
|