Bind cascading dropdown by ajax/json in MVC application

An Asp.net MVC developer can use this code to bind cascading drop down by ajax/json . Let’s say we have country drop down. When user selects country, states of selected country will be filled by json. (See below image)

Dropdown fill by json

First dropdown bind by retaining view bag by controller and for second drop down we can use JavaScript/Jquery to fill value based on selected country.

Below code used on cshtml page:

<div class="editor-label">
                @Html.LabelFor(m => m.Country)
            </div>
            <div class="editor-field">
              @Html.DropDownListFor(model => model.Country, new SelectList(Model.Country, "Value", "Text"), "Select Contry", new { onchange = "CountryChange()" })                                                                                                                   
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.State)
            </div>
            <div class="editor-field">
                @Html.DropDownList("state","Select State")
            </div>

We have used “CountryChange()” javascript function to fetch and fill data in state dropdown based on country change. Below is the JavaScript function implementation.

<script language="JavaScript" type="text/JavaScript">
    function CountryChange () {
        var url = '@Url.Content("~/Account/GetState")';

        var ddlsource = "#Country";
        var ddltarget = "#State";

        if ($(ddlsource).val() != "") {
            $.ajaxSetup({ cache: false });
            $.getJSON(url, { Sel_Country: $(ddlsource).val() }, function (data) {

                $(ddltarget).empty();

                $("#State").append("<option  value=''>Select State</option>");

                $.each(data, function (index, optionData) {
                    $("#State").append("<option value='" + optionData.Value + "'>" + optionData.Text + "</option>");
                });
            });
        }
        else {
            $("#State").empty();
            $("#State").append("<option value=''>Select State</option>");
        }
    }
</script>

Here json url specified “~/Account/GetState” is method “GetState” available in “Account” controller to retrieve data and pass data in json format.

public JsonResult GetState (string Sel_Country)
        {

            CountryService db = new CountryService ();
            JsonResult result = new JsonResult();
            var vStateList = db.GetStateList(Convert.ToInt64(Sel_Country));
            result.Data = vStateList.ToList();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            return result;
        }

Based on this approach developer can fill dropdown or fetch any kind of server side data and fill in the page by Jquery without postback.

Feel free to write your questions in comments.

Enjoy Programming!!
Amit Patel

About these ads

In MVC controller returns rendered html

In MVC development sometime developers need to get rendered html code from controller’s action method. In my one of the requirement I am updating page’s specific portion by java script by json method, so I am updating returned html in related tag by jquery.

Below are the code and description of the solution.

In Below action method is about for refresh page’s section and return new updated HTML.

public JsonResult RefreshPage(string SectionID)
{
   JsonResult result = new JsonResult();
   // My bussiness logic to get data
   string StrReturn = RenderViewToString("HomePage", oTS.Data, this.ControllerContext);
   result.Data = StrReturn.ToString();
   result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
   return result;
}

In this method We have used RenderViewToString method to get rendered html, here “HomePage” is my partial view for this which is actual bind oTS.Data data and generate html.

Below is the method for RenderViewToString

public string RenderViewToString(string viewPath, object model, ControllerContext context)
{
       var viewEngineResult = ViewEngines.Engines.FindPartialView(context, viewPath);
       var view = viewEngineResult.View;
       context.Controller.ViewData.Model = model;
       string result = String.Empty;
       using (var sw = new StringWriter())
       {
           var ctx = new ViewContext(context, view,
                                     context.Controller.ViewData,
                                     context.Controller.TempData,
                                     sw);
           view.Render(ctx, sw);
           result = sw.ToString();
       }
       return result;
}

So in this way we can return html. and that html will be used by below jquery method by json.

 function RefreshPage() {
        var hiddenID = $('#hdTDetailsID').val();
        var url = '@Url.Content("~/page/RefreshPage")';
        $.ajaxSetup
        (
            {
                cache: false
            }
        );
        $.getJSON(url,
         {
             Sel_TDetailID: hiddenID
         },
        function (data) {
            $(divname).html(data);
        });
    }

In this way we can refresh page’s any of the portion’s data by jquery in MVC. There are other various ways to do it but when you append some data in current data then this approach is useful.

Feel free to write me in case of any question or need more details on this.

Thanks,
Amit Patel
“Enjoy Programming”

Redirection by AJAX request in MVC application.

This article is basically for MVC developer whom is using AJAX in their application.

Problem:
In my application I have created common login control (partial view) that I have used in various places but when I was submitting the form that is redirecting to different URL based on loaded controller so where I need to write login logic in common place. So to resolve this I have used AJAX so that form is on same place always use only one action method. I have used on div for updatedtargedid to update on each request.

But in this case, I am also facing an issue when I am redirecting to another page (after success login) that is open all redirected page in my login div (mean targeted id). So I need to resolve it, if any validation error and control back to login then thing is working fine because control is loaded in updatedtarged id.

This article is basically covers below three scenarios/problems

  • AJAX in MVC
  • How to update current div or form
  • Redirection by AJAX request in MVC application.

Below are the my code for this.

<div id="loginControl">
@using (Ajax.BeginForm("Login", new AjaxOptions { UpdateTargetId = "loginControl", InsertionMode=InsertionMode.Replace }))
{
    
        <div class="login_pannel">
            @if (Html.ValidationSummary(true) != null && Html.ValidationSummary(true).ToString() != string.Empty)
            {
                @Html.ValidationMessage("", new { @class = "reqtext" })            
            }
Your User ID
            <br />
            @Html.TextBoxFor(m => m.UserName, new { @class = "login_box" })
            <br />
            @Html.ValidationMessageFor(m => m.UserName, null, new { @class = "reqtext" })<br />
Your Password
            <br />
            @Html.PasswordFor(m => m.Password, new { @class = "login_box" })
           <br />
            @Html.ValidationMessageFor(m => m.Password, null, new { @class = "reqtext" })
<input name="login" type="submit" value="Login" class="button" />
}
</div>

In this above code I have used Ajax.BeginForm so that will be responsible set ajax request to the controller’s post method. And Once response back that will update only “loginControl” id, Which is specified as Div id. (you can see in code).

Once you submit form that will executes controllers login action method.

public ActionResult Login(LogOn Model)
        {
            if (ModelState.IsValid)
            {
			LogOnservices dbLoginService = new LogOnservices();
                Users LogedInUser = dbLoginService.LogOn(Model);

                    if (LogedInUser != null && LogedInUser.Status == Convert.ToInt32(CommonEnums.UserStatus.Inactive))
                    {
                        ModelState.AddModelError("", “In Active User”);
                    }
                    else
                    {
                          string returnUrl = Url.Action("Index", "MyAccount");
                    		ViewBag.returnUrl = returnUrl;
                    			return PartialView("_Login", model);

                    }
                }
            }
            return PartialView("_Login", Model);
}

So if any error then return “_login” view by partialView. And replace div id with returned div.
Here I have faced one problem is that when I am returning to current div then that is overlapping on another div mean each time that is rendered another div so that results changed UI or give JavaScript errors.

So I have added this property in Ajax form to resolve this issue :

InsertionMode=InsertionMode.Replace

Now I am facing one another problem is that when user succesfull login and redirecting to another page then also system open new window in targeted div id rather than in full page.

Previously I have added code like below. That is redirect but open page in targeted id, with very strange UI.

return RedirectToAction("Index", " MyAccount");

This is because of returned partial view is loading in targeted div id due to AJAX Request.

So This need to handle in JavaScript. So I have created one ViewBag with return url and if that has some value then javascript is redirecting to provided url.
Below are the code is helpful to me to resolve this issue.

Created Viewbag :

string returnUrl = Url.Action("Index", "CDashBoard");
                    		ViewBag.returnUrl = returnUrl;
                    			return PartialView("_Login", model);

Redirection by Javascript:

<script language="javascript">

    function Redirect() {
        var returnUrl = "@ViewBag.returnUrl";
        if (returnUrl) {
            window.location.href = returnUrl;
        }
    }
    Redirect();
</script>

So With this code now my redirection and login control is works fine in all senario with code/ui reusablities.

Thanks
Amit Patel
"Enjoy Programming"

Add any customize text in crystal reports by .net code

In my requirement I have to show few search parameter in crystal reports which is passed from aspx page.
And that is not hard coded fixed because I have 10-15 parameters and I want to place it dynamically if whatever parameter’s value available that only needs to be attach in reports.

So I have implemented this by below approaches.
In Crystal reports rpt file I have take one default fields with “SearchTextRight” and “SearchTextLeft” to display value left and right side corner.

This both fields “CanGrouw” property set as “True” and attach each of the search parameter by “\n” so automatically new line added and text object’s height will increased.
Below are the code we have used for that.

 ReportClass rptH = GenerateReportClasss(Server.MapPath("~/Reports/GetReortData.rpt"));
            
            /// Attach serarch fields

            SearchDraw oSearchDrow = AttachCustomerHours(collection);
            if (oSearchDrow.SearchingStringLeft != string.Empty)
            {
                TextObject SeachTextLeft = (TextObject)rptH.ReportDefinition.ReportObjects["SearchTextLeft"];
                SeachTextLeft.Text = oSearchDrow.SearchingStringLeft;
            }
            if (oSearchDrow.SearchingStringRight != string.Empty)
            {
                TextObject SeachTextRight = (TextObject)rptH.ReportDefinition.ReportObjects["SearchTextRight"];
                SeachTextRight.Text = oSearchDrow.SearchingStringRight;
            }
            AttachLocalizationCustomerHours(rptH);
            rptH.Refresh();

            rptH.SetDataSource(Ds.Tables[0]);

Now all text will attached in reports’ PDF or excel file.

Let me know for more details

Thanks,
Amit Patel
amitpatel.it@gmail.com
“Enjoy Programming”

URL Encryption in MVC Application

In any web application there are always security related problem occurs when user
change something in URL’s value.

Like in URL sending passing any id in navigation from one page to other page to
display relevant data or perform any of the operation.

When passing any sensitive data from navigation then it may problem occurs when use
can change it and hake any of the data.

So better option is store this value in session but every time this is not
possible or good solution to store in session.

So in this article I am taking about URL encryption and decryption with any of the
data.

So we have created below methods for URL encryption and decryption in one the common
class.

public static string URLEncrypt(string toEncrypt)
        {
            string strEncoded = Security.EncryptURL(toEncrypt, true);
            return strEncoded;
        }
        public static string URLDecrypt(string toDecrypt)
        {
            string strDecoded = toDecrypt;
            strDecoded = Security.EncryptURL(strDecoded, true);
            
            return strDecoded;
        }

Here I am using Encryption methods by triple tipple cryptography algorithm.
Below are then complete details of this

http://amitpatelit.wordpress.com/2011/02/25/encrypt-and-decrypt-by-c-code-by-cryptography/

now we have to pass each id with encrypted format, as below given code. This code needs to apply on all available view where we are passing in data id.

@{
        string EncryptID = "";
        EncryptID = Security.URLEncrypt(item.ID.ToString());
}           
   @Html.ActionLink("Edit", "Edit", new { id= EncryptID }) |
   @Html.ActionLink("Details", "Details", new { id= EncryptID }) |
   @Html.ActionLink("Delete", "Delete", new { id= EncryptID })

And this passed ID need to decrypt in controller before use in actual logic.

public ActionResult Edit(string id)
{
	long intid = Convert.ToInt64(Security.URLDecrypt(id));

            Language language = db.Language.Find(intid);
            return View(language);
}

That above decryption need to apply all available methods where we have encrypted passed id.

So In this way you ULR will be secured with pass any kind of data in encryption format.

Thanks,
Amit Patel
“Enjoy Programming”

Crystal Reports in MVC

Below are the code for implement crystal reports in MVC with support of export to PDF and Excel format.

MVC rajor/aspx pages is not supporting report viewer so that is not possible to place report viewer where user can see reports and export that in required format.
So in MVC we have directly deal with report class and generate PDF/Excel and sent to client with browsers functionality view and download.

View: In view required all search parameter and with Generate report button (PDF/Excel)

Contollor : based on provided search parameter fetch data and bind with crystal reports class and generate PDF/excel and sent to client’s browser for download.

Below the are the code for controller to generate and send file to client’s browser.

ReportsServices dbReportsServices = new ReportsServices();
ReportClass reortptH = new ReportClass();
            reortptH.FileName = Server.MapPath("~/Reports/ReportData.rpt");

reortptH.Load();

DataSet Ds = dbReportsServices.FetchData("GetData"); // exectures store procedure to retrieve data

reortptH.SetDataSource(Ds.Tables[0]);

bool IsPDF = Convert.ToBoolean(collection.Get("IsPDF")); // In view add two button for export to PDF and excel and that will returs value on that way.

            if (IsPDF)
            {
                System.IO.Stream stream = rptH.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
                return File(stream, "application/pdf", "ReportData.pdf");
            }
            else
            {
                System.IO.Stream stream = rptH.ExportToStream(CrystalDecisions.Shared.ExportFormatType.Excel);
                return File(stream, "application/xls", "ReportData.xls");
            }

Post your comments if you have questions/comments.

Thanks,
Amit Patel
amitpatel.it@gmail.com
“Enjoy Programming”

Execute Store procedure in Entity framework

In MVC application generally we are using entity frame work (dbcontext) to manage and retrieve database related operation, but in some case suppose we have few complex logic for that need to write store procedure so below are the code for retrieve data from store procedure in MVC Mode by entity frame work.
In this class I have inherited by “DBContext” class so “Database” is part of data context.

public List<Menu> GetMyData(long intUserID)
{
List<Role> oMenuList = new List< Role >();
Business.Model. Role oRole = new Role ();
oMenu.MenuId = 1;
List<Role> oMenuDataList = this.Database.SqlQuery<Menu>("exec GetRoleData {0}", intUserID).ToList<Role>();
}

In Above code List<Role> Role is model so that is fill by storeprocedure “GetRoleData”.

Let me mail:amitpatel.it@gmail.com for any questions.

Thanks

Amit Patel

“Enjoy Programming”

Add Service layer in MVC

Create Service Layer from MVC

In MVC + Entity framework has certain change is that how can we introduce service layer or any code level business layer which responsible to data management with executes store procedure.

MVC Architecture

MVC Architecture

So I have introduce a service layer with is write business logic based on model.

Model Structure

 

In general I  have added all model in one separate project and there we have add one service class for each model (some time more then one model belongs to one single service class.

Entity framework

For handle entity framework we have created one common “serviceBase” class that will be inherited by all services class, in this service class we have maintained all related common items like connection string binding and remove conversation. This class is basically belongs to “DBContext” as part of entity frame work.

Model:

public class Country

{

public int ID { get; set; }

[StringLength (100)]

public string CountryName { get; set; }

[StringLength(500)]

public string Remarks { get; set; }

public int LanguageID { get; set; }

public bool IsActive { get; set; }

public virtual ICollection&lt;Users&gt; Users { get; set; }

}

}

 

Service class:

 

namespace Business.Model.Services
{
public class CountryService : ServiceBase
{
public DbSet<Country> Country { get; set; }
public void InActiveContry(int id)
{
// write any of the logic
}

//public DbSet<Player> Players { get; set; }


}
}

 

Controller:

 

Custom validation in MVC application

In MVC for adding a validation there is need to set attributes and there are few inbuilt validation attributes related classes are available and based on that we can set validation.

But in practical scenario there are another couple of validation needs to required implement with our customer logic and also important part is that add message from resource file to handle multilingual support.

Read more of this post

Error Log in MVC

Implement Elmah in MVC Application for error log

In Every application capture and maintain error log is very important part of the any application. That is help full to development support team as well client to make application running a smooth in live environment

So implementing different error log for every application we need to add few efforts so elmah has good common solution for that. Elmah can be fit in any .net application with below error log mechanism.

  1. Log in XML file
  2. Log in SQL database
  3. Log in Mail (sent an email to provided email address)
  4. Log in Oracle database
  5. Log in Access database

Elmah is Open source code so you also download a code also for any modification. Below is the URL for Elmah code and download.

http://code.google.com/p/elmah/

Along with this kind of feature they are providing good UI also to view all log with details along with download functionality.

In this article I am targeting to how to configure Elmah in MVC 3.0 Application

That is very simple to add Elmah in MVC application, just need to add elmah in project from package library reference.

Select Project > Click on Right Click > Select “Add Library Package Reference”  and search elmah and install that in your application.

Now you have to add below xml tag in your web.config file.

Add below ConfigSection (if tag exist then add tag in that existing tag)

 

Now Add Elmah tag in below this configSection. Where you can uncomment what ever you want and add your setting.(like database name, log file path etc…)

<elmah>
    <!--
            Use to log errors to Microsoft SQL Server 2000 or 2005
            using ASP.NET 2.0. Set value of connectionStringName attribute
            to the name of the connection string settings to use from
            the <connectionStrings> section.
        
        <errorLog type="Elmah.SqlErrorLog, Elmah" 
            connectionStringName="..." />
        -->
    <!--
            Use to log errors to Microsoft SQL Server 2000 or 2005
            using ASP.NET 1.x and adjust the value of connectionString 
            attribute to your settings.

        <errorLog type="Elmah.SqlErrorLog, Elmah" 
            connectionString="Data Source=.;Initial Catalog=ELMAH;Trusted_Connection=True" />
        -->
    <!--
            Use to log errors to MySQL 5.0+  Set value of connectionStringName attribute
            to the name of the connection string settings to use from the <connectionStrings>
            section.

        <errorLog type="Elmah.MySqlErrorLog, Elmah" 
            connectionString="..." />
        -->
    <!--
             Use to log errors to a SQL Server Compact 4 database file (requires .NET 3.5 SP1) 
             Set value of connectionStringName attribute to 
             the name of the connection string settings to 
             use from the <connectionStrings> section.
    
          <errorLog type="Elmah.SqlServerCompactErrorLog, Elmah" connectionStringName="..." />

             The format of the connection string should be as follows:
    
          <connectionStrings>
            <add name="..." connectionString="data source=[path to the database file]" />
          </connectionStrings>
    
            Replace the content of the brackets with a file name, for example:
    
          data source=C:\Elmah.sdf
    
             If the database file doesn't exist it is created automatically.
             You can also place the file in the App_Data folder, by using the |DataDirectory| macro:
    
          <connectionStrings>
             <add name="..." connectionString="data source=|DataDirectory|\Elmah.sdf" />
          </connectionStrings>

      -->
    <!--
            Use to log errors to SQLite using ASP.NET 2.0. 
            Set value of connectionStringName attribute to 
            the name of the connection string settings to 
            use from the <connectionStrings> section.
            
        <errorLog type="Elmah.SQLiteErrorLog, Elmah" connectionStringName="..." />
        
            The format of the connection string should be as follows:
            
        <connectionStrings>
          <add name="..." connectionString="data source=[path to the database file]" />
        </connectionStrings>
            
            Replace the content of the brackets with a file name, for example:
            
        data source=C:\Elmah.db
            
            If the database file doesn't exist it is created automatically.
            To specify a path relative to and below the application root, 
            start with the root operator (~) followed by a forward slash (/), 
            as it is common in ASP.NET applications. For example:
            
        data source=~/App_Data/Error.db
        -->
    <!--
            Use to log errors into separate XML files that are stored on 
            disk at the path specified in the logPath attribute.
-->
    <errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/ErrorLog" />
    <!--
            Use to log errors to Oracle
            using ASP.NET 2.0. Set value of connectionStringName attribute
            to the name of the connection string settings to use from
            the <connectionStrings> section.
        
            The schemaOwner parameter is *optional*. Use this if the owner of the
            ELMAH package (pkg_elmah$error) is not the same user that you are 
            using to connect to the database.
            
        <errorLog type="Elmah.OracleErrorLog, Elmah" 
            schemaOwner="xxx" />
            connectionStringName="..." />
        -->
    <!--
            Use to log errors to Oracle
            using ASP.NET 1.1 and adjust the value of connectionString 
            attribute to your settings.

            The schemaOwner parameter is *optional*. Use this if the owner of the
            ELMAH package (pkg_elmah$error) is not the same user that you are 
            using to connect to the database.

        <errorLog type="Elmah.OracleErrorLog, Elmah" 
            schemaOwner="xxx" />
            connectionString="Data Source=xxxx;User ID=username;Password=password" />
        -->
    <!--
            Use to log errors to Microsoft Access
            using ASP.NET 1.x and adjust the value of connectionString 
            attribute to your settings.
            Use Elmah.mdb as your database.

        <errorLog type="Elmah.AccessErrorLog, Elmah" 
            connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Elmah.mdb" />
        -->
    <!--
            Use to log errors to Microsoft Access
            using ASP.NET 2.0. Set value of connectionStringName attribute
            to the name of the connection string settings to use from
            the <connectionStrings> section.
            Use Elmah.mdb as your database.
        
        <errorLog type="Elmah.AccessErrorLog, Elmah" 
            connectionStringName="..." />
        -->
    <!--
            Use to log errors to PostgresSQL 
            using ASP.NET 2.0. Set value of connectionString to a 
			valid Npgsql connection string.
        
		<errorLog type="Elmah.PgsqlErrorLog, Elmah" 
            connectionString="Server=...;Port=...;Database=...;User Id=...;Password=...;" />
        -->
    <!--
            Use to send error reports by e-mail and adjust the attributes
            according to settings desired. Note that only the from and
            to attributes are required. The rest are optional and may
            be removed. If the SMTP server does not require authentication,
            you MUST remove the userName and password attributes or
            set them to empty values (resulting in zero-length strings).
            If you are using ELMAH compiled for .NET Framework 1.x, then
            the to attribute may contain multiple recipient addresses,
            each of which must be delimited by a semi-colon(;). If you are 
            using ELMAH compiled for .NET Framework 2.0 or later, then the
            to attribute may contain multiple recipient addresses,
            each of which must be delimited by a comma (,).

        <errorMail 
            from="elmah@example.com" 
            to="admin@example.com" 
            subject="..."
            priority="Low|Normal|High"
            async="true|false"
            smtpPort="25"
            smtpServer="smtp.example.com" 
            useSsl="true|false"
            userName="johndoe"
            password="secret" 
            noYsod="true|false" />
        -->
    <!--
            Use to send short error messages to a twitter account.
        <errorTweet 
            userName="johndoe" 
            password="secret" />
        -->
    <!--
            Use to prevent errors from being mailed or logged based on
            assertions. An assertion evaluates the current context, resulting
            in a Boolean outcome. An error is filtered if the assertion results
            in true. For a more detailed explanation, see:

http://code.google.com/p/elmah/wiki/ErrorFiltering

            The example below will filter errors when any of the
            following conditions occur:
            
            - The status code is set to 404 
            - The root/base cause is System.IO.FileNotFoundException
            - The root/base cause is System.Web.HttpRequestValidationException
            - The user agent making the request identifies itself as "crawler"
            - The request is from the local machine
            
            The assertion below is expressed as a JScript expression and is the
            most generic and simplest of the assertions to use if you are
            familiar with the JavaScript language. It can work in Medium and
            Full trust environments.

        <errorFilter>
            <test>
                <jscript>
                    <expression>
                    <![CDATA[
                    // @assembly mscorlib
                    // @assembly System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
                    // @import System.IO
                    // @import System.Web

                    HttpStatusCode == 404
                    || BaseException instanceof FileNotFoundException 
                    || BaseException instanceof HttpRequestValidationException
                    /* Using RegExp below (see http://msdn.microsoft.com/en-us/library/h6e2eb7w.aspx) */
                    || Context.Request.UserAgent.match(/crawler/i)                      
                    || Context.Request.ServerVariables['REMOTE_ADDR'] == '127.0.0.1' // IPv4 only
                    ]]>
                    </expression>
                </jscript>
            </test>
        </errorFilter>
        -->
  </elmah>

If you are using IIS 7 then add this tag in your tag.

Now you when error occurs log file will be automatically generated. And that you can access by just calling elmah.axd from your root path. That will display all logs with details description.

One more thing need to consider in MVC application, when error mode is On that error log in not captured by default because in MVC that will not execute application_error event so log is not generated in xml file.
Hence, you have to comments handler related filter in global.aspx file

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute());
}

Let me know if you have any questions or suggestion on this post.

Thanks,
Amit Patel
“Enjoy Programming”

Follow

Get every new post delivered to your Inbox.

Join 218 other followers