Tuesday, 8 July 2014

Get the values from http query string variables in View in ASP.NET MVC

This method can be used in any view but it is recommended to make sure your ViewModel contains all necessary information. We are going to use this approach in layout page, as normally layout page does not have any model(it can have but then it might get very messy and personally I think for big projects it could be extra constraint).

Consider a situation in which you are interested in values for variables from http request.

http://localhost:49853/Home/Index?searchType=global

In above address we are passing variable searchType. Let's assume that searchType can have 2 different values - local and global.

In your main css file:

#mainNav.global {
  background: #404939; }
  #mainNav.global nav.nav {
    background: none; }
    #mainNav.global nav.nav .top {
      background: #404939; }
    #mainNav.global nav.nav a:hover, #mainNav nav.nav a.active {
      background-color: #7dc243; }
     
      #mainNav.local
      {
          background: #3C7987; }
        #mainNav.localnav.nav {
                  background: none; }
        #mainNav.local nav.nav .top {
                          background: #3C7987; }
        #mainNav.local nav.nav a:hover, #mainNav nav.nav a.active {
                        background-color: #7FDCFF; }

In layout page in _Layout file header section:
<header>
        <div class="content-wrapper">
            <div class="float-left">
                <p class="site-title">@Html.ActionLink("your logo here", "Index", "Home")</p>
            </div>
            <div class="float-right">
                <section id="login">
                    @Html.Partial("_LoginPartial")
                </section>
                @{
                    string searchClass = "global";
                    if (HttpContext.Current.Request.Params["searchType"] == "local") 
                    {
                        searchClass = "local"; 
                    }
                }
                <div id="mainNav" class=@searchClass>
                    <nav class="nav" data-nav>
                        <ul>
                          
                            @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "searchForm" }))
                            {
                                @Html.ActionLink("Global","Index","Home", new { searchType= "global" }, null)
                                @Html.ActionLink("Local","Index", "Home", new { searchType = "local" }, null)
                                <input type="search" name="searchMode" value="" placeholder="Search...">
                                <input type="submit" name="submitBtn" value="Search">
                            }
                        </ul>
                    </nav>
                </div>
               <nav>
                    <ul id="menu">
                        <li>@Html.ActionLink("Home", "Index", "Home")</li>
                        <li>@Html.ActionLink("About", "About", "Home")</li>
                        <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                    </ul>
                </nav>
            </div>
        </div>
    </header>
So we are going to toggle class name for navigation bar. If we are in global searchType background color is #7dc243, in local searchType 7FDCFF.

If you are in global searchType your address is :
http://localhost:49853/?searchType=global




In local :

http://localhost:49853/?searchType=local

Thursday, 3 July 2014

Passing object from view to partial view with ViewDataDictionary in ASP.NET MVC

There might be a situation where you have parent model that for instance hold list of objects that you want to pass to partial view. I prefer to not use View Data or ViewBag and make sure that view models I am using always hold information I want to access, but there might be some exceptions.

Take a look at this example
 @Html.Partial("_EditAddress", Model.AddressVM, new ViewDataDictionary { { "statesList", Model.stateList} })
Third parameter in constructor for Partial class is ViewDataDictionary. Using this we can replace ViewData for partial view.
statesList in this example is key and Model.stateList is data that parent Model holds.

To retrieve the data in partial view access it like you would normally access ViewData and cast it to an object you are expecting.

So for instance if we are using dropdownlist helper :
@Html.DropDownListFor(m => m.stateId, new SelectList(ViewData["statesList"] as List<States>, "stateId", "name", "stateId"), "Select state")

Wednesday, 2 July 2014

Get current action and controller name in View in ASP.NET MVC

Being able to get action or controller name on view might come useful when you are using layout for every view(except partial views) in your application.

Layout view
 @if (Request.IsAuthenticated)
                        {
                            <ul>
                                <li>
                                    @Html.ActionLink("Dashboard", "Index", "Home")
                                </li>
                                <li>
                                    @Html.ActionLink("Account", "Manage", "Account")
                                </li>
                                <li>
                                    @Html.ActionLink("GetClients", "Index", "Client")
                                </li>
                                <li>
                                    @Html.ActionLink("Setting", "ListingForOrganisation", "Settings")
                                </li>
                               
                                @if (HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString() == "Client")
                                {
                                <li><span>Add Client</span>
                                    <ul>
                                        <li>
                                            @Html.ActionLink("Temporary client", "AddTemporaryClient", "Client")
                                        </li>
                                        <li>
                                            @Html.ActionLink("Permanent", "AddPermanentClient", "Client")
                                        </li>
                                    </ul>
                                </li>
                                }
                            </ul>
                        }

(HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString() == "Client")
will check if request came from Client controller and if so extra feature will appear.

To get action name replace simply use 
(HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString() == "Action name") 



Tuesday, 22 April 2014

Prevent displaying Log In page in partial view on ajax request after session expired in ASP.NET MVC

If you are using partial views with many ajax request, there might be a situation in which user session expires and if you will try to submit form asynchronously via ajax  Log in page will be displayed in partial view(this will occur if you are using authorize attribute on the method you are calling).

Add this method to global.asax.cs file.

 // To use for ajax request when user session expired

protected void Application_EndRequest()
        {
            var context = new HttpContextWrapper(Context);
            // If we're an ajax request, and doing a 302, then we actually need to do a 401
            if (Context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
            {
                Context.Response.Clear();
                Context.Response.StatusCode = 401;
            }
        }
In main.js file or script section on your main view(cshtml file if using Razor) add this:
var  $document = $(document);

handleAjaxError = function (XMLHttpRequest, textStatus, errorThrown) {
    if (XMLHttpRequest.status == 401) {
        //refresh the page, as we are not longer authorized
        location.reload();
    }
    };
 
Since we already lost session, we want to refresh the page and user will be redirect automatically to Log in page, rather than displaying Log in page in small partial view.

    $document.ajaxComplete(function(event, XMLHttpRequest, AjaxOptions){
        handleAjaxError(XMLHttpRequest);
    }); 

http://api.jquery.com/ajaxComplete/ - More on ajax Complete method

http://stackoverflow.com/questions/3431343/asp-net-mvc-forces-an-ajax-request-be-redirected-to-the-login-page-when-the-form - Inspired by this post

Tuesday, 1 April 2014

Google adsense April Fools joke

After I logged in today to see if google made any April fools joke I discovered one on Ad sense earning page. Regions have been replaced by planets and moons. It might be quite funny at the moment, but in next 30-100 years it might be real.

Saturday, 15 March 2014

Submitting form with partial view in ASP.NET MVC

In this tutorial we want to submit form with partial model.

Download full project here

We are going to have ClientVM that will have partial view with Address model. 
Create new MVC 4 project, choose internet project and Razor.

Create models that we will use in this project.

Models
public class Client
    {
        public Client()
        { 
        }

        public Client(string firstName, string lastName, Guid addressId)
        {
            this.address = new Address();
            this.clientId = Guid.NewGuid();
            this.firstName = firstName;
            this.lastName = lastName;
            this.addressId = addressId;
        }

        public Guid clientId { get; set; }
        public string firstName { get; set; }
        public string lastName { get; set; }
        public Guid addressId { get; set; }
        public virtual Address address { get; set; }
    }

public class Address
{
    public Address()
    { 

    }

    public Address(string houseNumber, string streetName)
    {
    this.addressId = Guid.NewGuid();
    this.houseNumber = houseNumber;
    this.streetName = streetName;
    }

    public Guid addressId { get; set; }
    public string houseNumber { get; set; }
    public string streetName { get; set; }
}

View Models

 public class ClientVM
    {
        public ClientVM()
        { 
            
        }

        public ClientVM(Client client, Address address)
        {
            this.clientId = Guid.NewGuid();
            this.firstName = client.firstName;
            this.lastName = client.lastName;
            this.addressId = client.addressId;
            this.addressPartial = address;
        }

        public Guid clientId { get; set; }
        public string firstName { get; set; }
        public string lastName { get; set; }
        public Guid addressId { get; set; }
        public Address addressPartial { get; set; }

    }


In Home controller we will create ActionResult ClientInfo

public ActionResult ClientInfo()
        {
            // Normally we would get Client from database. For test we use constructors to define new     entries.

            Address address = new Address("25 A", "London street");
            Client client = new Client("Adam", "Bielecki", address.addressId);

            ClientVM viewModel = new ClientVM(client, address);

            return View(viewModel);
        }

and the same method to submit the form:

[HttpPost]
        public ActionResult ClientInfo(ClientVM viewModel)
        {
            return View(viewModel);
        }

In _Layout_cs change 2nd link for menu.

<li>@Html.ActionLink("Submit Partial Model", "ClientInfo", "Home")</li>

so menu tabs should look like that:

<ul id="menu">
                            <li>@Html.ActionLink("Home", "Index", "Home")</li>
                            <li>@Html.ActionLink("Submit Partial Model", "ClientInfo", "Home")</li>
                            <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                        </ul>

Now we have to create 1 view for ClientInfo and 1 partial view for Address.
Compile your project (Shift+Ctrl+B), right click ClientInfo in Home Controller and Add View.

Check Create a strongly-type view, choose ClientVM and scaffold template : Edit.





Right click on shared folder add view and call it _Address. Use the same setting as before, but this time select Address as your model class and check box "Create as a partial view".

Remove form from _Address partial view so it should like that:



@model PartialViewModelSubmission.Models.Address

<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

<h2>Address</h2>

    <fieldset>
        <legend>Address</legend>

        @Html.HiddenFor(model => model.addressId)

        <div class="editor-label">
            @Html.LabelFor(model => model.houseNumber)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.houseNumber)
            @Html.ValidationMessageFor(model => model.houseNumber)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.streetName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.streetName)
            @Html.ValidationMessageFor(model => model.streetName)
        </div>

      
    </fieldset>


Run the application, click Submit Partial Model and submit the form. 
As you can see we get error as Address have not been submitted.



 The reason why it is happening is due to binding issue. Let's fix it.

We will have to create partial class for Address. In Address.cs add this partial class:


public partial class AddressBase
{
   public virtual Address partialAddress { get; set; } 
}

Using virtual type we are going to lazy load Address.

 Modify ClientVM so it looks like that:




public class ClientVM : AddressBase
    {
        public ClientVM()
        { 
            
        }

        public ClientVM(Client client, Address address)
        {
            this.clientId = Guid.NewGuid();
            this.firstName = client.firstName;
            this.lastName = client.lastName;
            //this.addressId = client.addressId;
            //this.addressPartial = address;
            this.partialAddress = address;
            
        }

        public Guid clientId { get; set; }
        public string firstName { get; set; }
        public string lastName { get; set; }
        // public Guid addressId { get; set; }
        // public Address addressPartial { get; set; }
    
}

ClientVM inherit from AddressBase partial class so we can assign address to base.
            this.partialAddress = address;

This is all you have to do for classes, we have to amend views a bit as well.

In ClientInfo we are going to pass ClientVM model to address so change it to :
@Html.Partial("_Address", Model)

In _Address view change model to AddressBase and update scaffolding so it should look like that:

@model PartialViewModelSubmission.Models.AddressBase

<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

<h2>Address</h2>

    <fieldset>
        <legend>Address</legend>

        @Html.HiddenFor(model => model.partialAddress.addressId)

        <div class="editor-label">
            @Html.LabelFor(model => model.partialAddress.houseNumber)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.partialAddress.houseNumber)
            @Html.ValidationMessageFor(model => model.partialAddress.houseNumber)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.partialAddress.streetName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.partialAddress.streetName)
            @Html.ValidationMessageFor(model => model.partialAddress.streetName)
        </div>

      
    </fieldset>
Now run the application again and if you followed everything correctly you should be able to see Address model when you debug.








Sunday, 9 March 2014

How to hide querystring parameter name from an URL generated with Html.ActionLink in ASP.NET MVC

 In View we are going to create link using Html helper :
@Html.ActionLink("Address", "ViewAddress", new { addressId = Guid.NewGuid() })
that will give us :

http://localhost:100/Home/ViewAddress?addressId=5f89a656-e98c-4680-b98f-6a3cf4ede7aa

We want to hide query string addressId and have only :

 http://localhost:100/Home/ViewAddress/5f89a656-e98c-4680-b98f-6a3cf4ede7aa

The solution is to add new map route.

Open RouteConfig.cs file from App_Start folder and add new Map Route:
routes.MapRoute("ListingPreview", "Home/ViewAddress/{addressId}",
                new
                {
                    controller = "Home",
                    action = "ViewAddress",
                    addressId= UrlParameter.Optional
                }
                );