European ASP.NET MVC Hosting

BLOG about Latest ASP.NET MVC Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET MVC Hosting :: Basic Routing in ASP.NET MVC

clock January 30, 2019 10:22 by author Scott

When getting started with ASP.NET MVC and/or the ASP.NET Web API, it can be overwhelming trying to figure out how it all works. These frameworks offer powerful features, and abstract away a good deal of pain associated with handling, routing, and responding to HTTP requests within an application. This is a great thing for seasoned developers who understand what it is the framework is doing “for” you (and how to modify that behavior, if desired). It also makes it easier for new or less-experienced folk to set up a basic site or API and watch it “just work.”

On the other hand, the abstraction can make it challenging for those new to the MVC world to understand just what is going on, and where the critical functionality they want to modify “lives.”

One of the fundamental concepts to understand when using ASP.NET MVC and/or the ASP.NET Web API is routing, which essentially defines how your application will process and respond to incoming HTTP requests.

Routing Makes it All Work

Traditional web communication architecture maps a URL (Uniform Resource Locator) to a file within the file system. For example, the following:

http://mydomain.com/mybooks/favorites.html

would tend to map to a file named favorites.html, in the directory ~/mybooks/favorites, located in the root directory for the site mydomain.com. In response to an incoming HTTP request for this resource, the contents of the file are either returned (as in the example above, as HTML) or perhaps code associated with a file is executed (if, for example, the file were a .aspx file).

Within the MVC framework, as well as the Web API*, URLs are instead mapped to specific methods which execute in response to the incoming request, generally returning either a View (MVC) or some sort of structured data (Web API) corresponding to the the requested resource. In other words, instead of pointing to actual physical resources within a file system, MVC and Web API routes instead point to an abstraction which represents the resource requested, in both cases a method which will return the requested item.

This de-coupling of the URL from the physical file system allows us to construct cleaner, more friendly URLs which are more beneficial to the user, search-engine-friendly, and (in theory) more persistent, meaning URLs associated with specific content are less likely to change, and break incoming links. 

How Routing Works in ASP.NET MVC

In MVC, the convention is to map URLs to a particular action (a method) on a particular controller. The action then executes, and (usually, but not always) returns an instance of ActionResult. The ActionResult class handles Framework logic such as rendering to HTML or JSON, and writing to the HTTP response that will be returned to the user’s browser.

Once again, I defer to the authors of ASP.NET MVC 4 (who happen to also be members of the ASP.NET team):

The most basic version of this convention would be a URL as follows:

http://mydomain/controllername/methodname

In an MVC project, this is achieved by registering route templates which establish how incoming URLs will be mapped to specific controllers and actions. A typical MVC project defines a Global.asx file, which contains a single method – Application_Start. Within this method, calls are made to various configuration methods to set up the application’s working state. One of these calls is to the RegisterRoutes method of the RouteConfig class found in the App_Start folder of the project.

Global.asx File and the RouteConfig File in a Typical MVC Project:

If we examine the Global.asx file, we find the following code:

The Default ASP.NET MVC Global.asx File:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

For our purposes, we are interested only in the call to RouteConfig.RegisterRoutes. As we can see, the call passes the the Routes collection of the Global RouteTable as a parameter to the RegisterRoutes method, which then populates the routes collection with pre-defined route templates for the application. The default MVC project template comes with a single pre-configured route:

The Default MVC RouteConfig Class:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new
            {
                controller = "Home",
                action = "Index",
                id = UrlParameter.Optional
            }
        );
    }
}

Note that any MVC application must have at least one route definition in order to function. In the above, a route template named “Default” is added to the routes collection. The items in curly braces enclose Route Parameters, and are represented by the parameter name as a placeholder between the curly braces. Route Segments are separated by forward slashes (much like a standard URL). Notice how the implied relative URL our route specifies matches the MVC convention:

~/{controller}/{action}

Route parameters can be named just about anything, however ASP.NET recognizes a few special route parameter names, in particular {controller} and {action}, and treats them differently than other route parameters.

Controller Matching

When the routing framework encounters a route parameter named {controller}, it appends the suffix “Controller” to the value of the parameter, and then scans the project for a class by that name which also implements the System.Web.Mvc.IController interface. Note that the search for a controller with a matching name is case-insensitive.

Action Matching

Once the framework has selected the proper controller, it attempts to locate an action on the controller with a name matching the {action} parameter value. The search for a matching action name is case-insensitive. If more than one action matches by name (as with multiple overloaded methods on the same controller), the framework will select the method for which the most URL parameters match method arguments by name.

Action Parameter Matching

Additional URL Parameters other than {controller} and {action} are available to be passed as arguments to the selected Action method. The framework will evaluate the input arguments of the available actions, and match them by name (case-insensitively) to the URL parameters other than {action} and {controller}. With certain restrictions, the framework will select that action with the greatest number of matching parameters.

Some things to consider:

  • The MVC framework will first match method arguments by name to URL parameters. Then, it will attempt to match any query string parameters included in the URL by name. If the request is a POST, then the framework will attempt to match the contents of the POST body.
  • Method arguments are evaluated for a match by name only. The framework does not consider the type required by the method argument. For example, a URL parameter named {id} with a value of “John” will be considered a match for a method which accepts an int argument named id.
  • Action methods can be decorated with attributes which restrict the type of HTTP request they will respond to. Such attributes indicate the applicable HTTP verb to which the action will respond.

As an example of limiting the HTTP actions which a method may respond, consider the following:

Overloaded Action Method with HttpPost Attribute:

public ActionResult Edit(int id)
{
    return View();
}
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    try
    {
        // TODO: Add update logic here
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}
 

In the above, we find two methods named Edit. The first accepts an int named id as an argument, and the second accepts an int named id and a FormCollection (a complex type). The purpose of this overloaded method is so that a browser can:

  • Request a view with which to edit a record of some sort and then,
  • Submit the modified record values back to the site for storage.

The first Edit method, which requires only an int id argument will be called using HTTP GET, and return a view with the current representation of the data to be edited. Once the user has updated values in the view and submits the form data, an HTTP POST request is issued. The overloaded Edit method, decorated with the [HttpPost] attribute, is executed, and the modified data is persisted or otherwise processed. 

The MVC Default Route Template – Routing Walk-Thru

The route mapping assumes that the URL template specified is relative to the domain root for your site. In other words, since the entire application is hosted at http://yourdomain.com it is not necessary to include this domain root as part of the route template.

In the case of the default MVC mapping from our RouteConfig class above, the route contains the two special parameters, {controller} and {action}. In processing incoming requests, the framework appends “Controller” to the value provided for the {controller} parameter, and then searches the project for a controller class of that name. Once the proper controller has been identified, MVC next looks for a method name corresponding to the value of the {action} parameter, and then attempts to match any additional parameters with input arguments accepted by that method.

For example, if our application receives a request with the following URL:

http://mybookstore.com/books/details/25

the routing will match the default template. The string “Controller” will be appended to the “books” segment, and the runtime will set about searching the project for a class named BooksController. If the controller is located, MVC will then examine the controller for a public method named Details. If a Details method is found, MVC will attempt to find an overload which accepts a single argument named id, and then calls that method, passing in the final URL segment (“25” in this case) as an argument.

The following controller example would provide a suitable match for our incoming request:

A Simple Books Controller:

public class BooksController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    public ActionResult Details(int id)
    {
        return View();
    }
}

The incoming request would result in a call to the Details method, passing in the integer 25 as the proper id argument. The method would return the appropriate view (how MVC does this is another convention for another post – let’s stay focused on request routing for now).

Route Parameter Defaults

Notice in the RegisterRoutes method, the registration of the “Default” route also appears to assign some default values to the controller and action, parameters. These values will be used for any of these parameters if they are missing from the incoming request URL. Additionally, the id parameter is designated as optional. For example, consider the following URL:

http://mybookstore.com/books/

In this case, we have specified the Books controller, but have not specified a value for the action or id. However, this route still matches our route definition, since MVC will provide the default value specified for the action parameter (in this case, index). Since the id parameter has been made optional in our route template, MVC will again search for a controller named BooksController, but in this case, examine the controller for a method named Index which does not require an argument. Again, a match is found, and the Index method is called, returning an appropriate view (most likely a list of all the books in the database).

The MVC default route mapping also specifies a default controller to use when no controller parameter is specified; namely, the “Home” controller. In other words, incoming requests to our domain root:

http://mybookstore.com/

will also match the default project controller. In this case, the runtime will attempt to locate a controller named HomeController, then locate the Index method of that controller. Since no id parameter was provided, the Index method will be called, returning the appropriate view ( most likely, the Homepage of our site).

What Next?

As we have seen above, MVC examines an incoming URL and attempts to map each URL segment to a controller and action according to the route templates set up in the RouteConfig.MapRoutesmethod. Once a proper controller and action have been identified, any additional URL segments (for example, the optional {id} segment in our example above) are evaluated against the action method signature to determine the best parameter match for the action.

But what happens when we need to do more than just send an ID in as an argument for the desired action method? Or, what if we have one or more overloaded methods by which we wish to perform more complex queries against our data?

While we can always include query parameters as part of our URL (and in fact we will no doubt have to resort to this at various points in our application design), we can customize and extend the default routing, and exert a little more control over how how and what our application will accept in an HTTP request by customizing our routes.

While the default /controller/action/id route baked into the MVC project template is a useful start and will handle many common controller cases, it is safe to say the MVC team did not expect developers to limit their applications to this minimally-flexible, single standard. Indeed, the ASP.NET routing framework (and the corresponding routing framework used by Web API) are very flexible, and within certain limits, highly customizable.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Creating Cascading DropDownList In ASP.NET MVC

clock January 23, 2019 10:46 by author Peter

I have used Entity Framework to fetch the values and used Database First approach. I would also write an article on an Entity Framework but today, I would just show you how to bind the cascading dropdown list in this blog.

I have two dropdownlists. One is for state and the other for city. I would populate the city, which is based on the state selection. You can add as many dropdownlists, as you want. For simplicity, I am using only two dropdowns.

Create table scripts
tblState
    CREATE TABLE [dbo].[tblState]( 
        [stateid] [int] NOT NULL, 
        [statename] [nvarchar](50) NULL, 
    PRIMARY KEY CLUSTERED  
    ( 
        [stateid] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] 
     
    GO  

tblCity

    CREATE TABLE [dbo].[tblCity]( 
        [Cityid] [int] NOT NULL, 
        [CityName] [nvarchar](50) NULL, 
        [stateid] [int] NOT NULL 
    ) ON [PRIMARY] 
     
    GO 
     
    ALTER TABLE [dbo].[tblCity]  WITH CHECK ADD FOREIGN KEY([stateid]) 
    REFERENCES [dbo].[tblState] ([stateid]) 
    GO 
 

I have tblState and tblCity, where I have stateid as Primary key in the tblState table and stateid as the Foreign key in tblCity table. You can insert states and cities from the database as you wish.

Now, with Entity Framework; create your EDMX file. In my case, I have named it ModelDemo.edmx.

Model
I have created a Model and named it Registration. This is not directly required but since I used a strongly typed View, so I have created Model. You can also add Model because if you write the httppost method to save the values to the database, then you would need the model.
    public class Registration 
    { 
    [Required(ErrorMessage = "Enter State")] 
            public string State { get; set; } 
    [Required(ErrorMessage = "Enter City")] 
            public string City { get; set; } 
    }  


Controller
Now, this is my Controller code.
    [HttpGet] 
    public ActionResult Details() 
            { 
                bindState(); 
                return View(); 
            } 
    -------------------------------- 
    public void bindState() 
            { 
                var state = objEF.tblStates.ToList(); 
                List<SelectListItem> li = new List<SelectListItem>(); 
                li.Add(new SelectListItem { Text = "--Select State--", Value = "0" }); 
     
                foreach (var m in state) 
                { 
     
     
                    li.Add(new SelectListItem { Text = m.statename, Value = m.stateid.ToString() }); 
                    ViewBag.state = li; 
     
                } 
            } 
    ---------------------------------- 
    public JsonResult getCity(int id) 
            { 
                var ddlCity = objEF.tblCities.Where(x => x.stateid == id).ToList(); 
                List<SelectListItem> licities = new List<SelectListItem>(); 
     
                licities.Add(new SelectListItem { Text = "--Select State--", Value = "0" }); 
                if (ddlCity != null) 
                { 
                    foreach (var x in ddlCity) 
                    { 
                        licities.Add(new SelectListItem { Text = x.CityName, Value = x.Cityid.ToString() }); 
                    } 
                } 
                return Json(new SelectList(licities, "Value", "Text", JsonRequestBehavior.AllowGet)); 
            }  


Now, if you see my Controller code, I have a httpget method Details(). I am then calling a non-action method bindState() to bind the state ddl. On selection of the state ddl, the getCity() method will be called to bind the city ddl. I have used jQuery to get the Id of the selected item and have passed it to the getCity method to get the cites for the selected state.

I have also used LINQ to get my desired select value w.r.t the Id passed.

View
Right click on action method Details(), followed by clicking Add View. I always prefer a strongly typed View and I have also created a strongly typed View in this case. The name of my View is Details.cshtml.

You need jQuery min.js. Just download it from the NuGet Package, if it’s not there.

    <script src="~/Scripts/jquery-1.10.2.min.js"></script> 
    <script type="text/javascript"> 
         
        $(document).ready(function () { 
     
            $("#State").change(function () { 
                $("#City").empty(); 
                $.ajax({ 
                    type: 'POST', 
                    url: '@Url.Action("getcity")', 
                    dataType: 'json', 
                    data: { id: $("#State").val() }, 
                    success: function (city) { 
     
                        $.each(city, function (i, city) { 
                            $("#City").append('<option value="' 
                                                       + city.Value + '">' 
                                                 + city.Text + '</option>'); 
                        }); 
                    }, 
                    error: function (ex) { 
                        alert('Failed.' + ex); 
                    } 
                }); 
                return false; 
            }) 
        }); 
    </script>  


I have added the jQuery-min.js. From the code given above, we get the Id of the state ddl.

    <div class="form-group"> 
    @Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-2" }) 
                <div class="col-md-10"> 
                    @Html.DropDownListFor(model => model.State, ViewBag.state as List<SelectListItem>, new { style = "width: 200px;" }) 
     
                    @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" }) 
                </div> 
            </div> 
     
            <div class="form-group"> 
     @Html.LabelFor(model => model.City, htmlAttributes: new { @class =     "control-label col-md-2" }) 
                <div class="col-md-10"> 
          @Html.DropDownListFor(model => model.City, new SelectList(string.Empty, "Value", "Text"), "--Select City--", new { style = "width:200px" }) 
     
                    @Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" }) 
                </div>   


I have used jQuery to get the ID of the state DDL on .change function and passed it to bind the city ddl.

Now, just run your Application and you should get the output given below and if you do not get it, then check that if you are getting any values in an Id in getCity() method. If not, then check for Id mis-match.

HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.

 



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Call Ajax Method Call with ASP.NET MVC?

clock January 8, 2019 11:41 by author Peter

In this tutorial, let me show you how to call ajax method in ASP.NET MVC.
Controller code here
    [HttpGet] 
    public JsonResult GetAjaxData(string newCode) { 
        return Json(new { 
            Status = "Ajax called succesfully", Message = "Message show succesfully" 
        }, JsonRequestBehavior.AllowGet); 
    } 

View Code Here

    @ { 
        ViewBag.Title = "Index"; 
    } < script src = "~/Scripts/jquery-1.8.2.js" > < /script> 
    <script> 
    function AjaxCall() 
    { 
    $.ajax({ 
    async: false, 
    url: $('#ajaxURL').val(), 
    type: 'GET', 
    cache: false, 
    data: { 
    newCode : "Put the data here" 
    }, 
    success: function (result) { 
    if(result.Status !=''){ 
    alert(result.Status); 
    } 
    else{ 
    alert('Ajax called failed'); 
    } 
    }, 
    error: function (result, textStatus, errorThrown) { 
    alert(errorThrown); 
    } 
    }) 
    } 
    </script > < div > < button value = "Ajax Called" 
    id = "btncalled" 
    onclick = "AjaxCall()" > Ajax Called < /button> 
    </div > @Html.Hidden("ajaxURL", Url.Action("GetAjaxData", "Demo")) 

App_Start-> route config.cs code here

    public static void RegisterRoutes(RouteCollection routes) { 
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
        routes.MapRoute( 
        name: "Default", 
        url: "{controller}/{action}/{id}", 
        defaults: new { 
            controller = "Demo", action = "Index", id = UrlParameter.Optional 
        }); 
    } 


I hope it works for you! Good luck!

HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.



ASP.NET MVC 5 Hosting - HostForLIFE.eu :: Limit Upload File Type Extensions Via Custom Data Annotation/Attribute

clock December 21, 2018 08:15 by author Peter

Restricting or limiting the file type extensions is a key business requirement. It is not necessary that a business allows all file types to be uploaded via their web application. Sometimes, only image files are accepted by the web application, sometimes only documents, and sometimes the combination of image, documents, and compressed file types are accepted by the web system.

Today, I shall be demonstrating the process of limiting/restricting the desired upload file type extensions by implementing custom data annotation/attribute component on ASP.NET MVC5 platform. This article is not specific to image files only, you can use the provided solution with any type of file format as well.

Following are some prerequisites before you proceed any further in this tutorial.

  • Knowledge of ASP.NET MVC5.
  • Knowledge of HTML.
  • Knowledge of Bootstrap.
  • Knowledge of C# Programming.

You can download the complete source code for this tutorial or you can follow the step by step discussion below. The sample code is being developed in Microsoft Visual Studio 2015 Enterprise.

Let's begin now.

Step 1

Create a new MVC web project and name it as "ImgExtLimit".

Step 2

You need to add/update the "executionTimeout", "maxRequestLength", and "maxAllowedContentLength" property values if not already added in the "Web.config" file, as shown below.
<system.web> 
  <authentication mode="None" /> 
  <compilation debug="true" targetFramework="4.5.2" /> 
  <!-- executionTimeout = 30hrs (the value is in seconds) and maxRequestLength = 1GB (the value is in Bytes) --> 
  <httpRuntime targetFramework="4.5.2" executionTimeout="108000" maxRequestLength="1073741824" /> 
</system.web>    
<system.webServer> 
  <!-- maxAllowedContentLength = 1GB (the value is in Bytes) -->     
  <security> 
    <requestFiltering> 
      <requestLimits maxAllowedContentLength="1073741824" /> 
    </requestFiltering> 
  </security>         
 
</system.webServer> 

 
executionTimeout -> Amount of time required to process your request on the web server. The value is provided in seconds.
maxRequestLength -> Maximum size which your request can capture and send to the web server. The value is provided in bytes.
maxAllowedContentLength -> Maximum allowed size of your content (e.g. file, text data etc.) that is sent to the web server. The value is provided in bytes.

Step 3
Open the "Views->Shared->_Layout.cshtml" file and replace the code with the following.
<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <title>@ViewBag.Title</title> 
    @Styles.Render("~/Content/css") 
    @Scripts.Render("~/bundles/modernizr") 
 
    <!-- Font Awesome --> 
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" /> 
 
</head> 
<body> 
    <div class="navbar navbar-inverse navbar-fixed-top"> 
        <div class="container"> 
            <div class="navbar-header"> 
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> 
                    <span class="icon-bar"></span> 
                    <span class="icon-bar"></span> 
                    <span class="icon-bar"></span> 
                </button> 
            </div> 
        </div> 
    </div> 
    <div class="container body-content"> 
        @RenderBody() 
        <hr /> 
        <footer> 
            <center> 
                <p><strong>Copyright © @DateTime.Now.Year - <a href="http://wwww.asmak9.com/">Asma's Blog</a>.</strong> All rights reserved.</p> 
            </center> 
        </footer> 
    </div> 
 
    @*Scripts*@ 
    @Scripts.Render("~/bundles/jquery") 
 
    @Scripts.Render("~/bundles/jqueryval") 
    @Scripts.Render("~/bundles/bootstrap") 
 
    @RenderSection("scripts", required: false) 
</body> 
</html>

In the above code, I have simply created a basic default layout page and linked the require libraries into it.

Step 4
Create a new "Helper_Code\Common\AllowExtensionsAttribute.cs" file and add the following code.
//----------------------------------------------------------------------- 
// <copyright file="AllowExtensionsAttribute.cs" company="None"> 
//     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose. 
// </copyright> 
// <author>Asma Khalid</author> 
//----------------------------------------------------------------------- 
 
namespace ImgExtLimit.Helper_Code.Common 

    using System; 
    using System.Collections.Generic; 
    using System.ComponentModel.DataAnnotations; 
    using System.Linq; 
    using System.Web; 
 
    /// <summary> 
    /// File extensions attribute class 
    /// </summary> 
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 
    public class AllowExtensionsAttribute : ValidationAttribute 
    { 
        #region Public / Protected Properties 
 
        /// <summary> 
        /// Gets or sets extensions property. 
        /// </summary> 
        public string Extensions { get; set; } = "png,jpg,jpeg,gif"; 
 
        #endregion 
 
        #region Is valid method 
 
        /// <summary> 
        /// Is valid method. 
        /// </summary> 
        /// <param name="value">Value parameter</param> 
        /// <returns>Returns - true is specify extension matches.</returns> 
        public override bool IsValid(object value) 
        { 
            // Initialization 
            HttpPostedFileBase file = value as HttpPostedFileBase; 
            bool isValid = true; 
 
            // Settings. 
            List<string> allowedExtensions = this.Extensions.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); 
 
            // Verification. 
            if (file != null) 
            { 
                // Initialization. 
                var fileName = file.FileName; 
 
                // Settings. 
                isValid = allowedExtensions.Any(y => fileName.EndsWith(y)); 
            } 
 
            // Info 
            return isValid; 
        } 
 
        #endregion 
    } 
}


In ASP.NET MVC 5, creating customized data annotations/attributes is one of the cool features. The ASP.NET MVC 5 platform already contains a default FileExtensions attribute, but, the issue with this pre-built data annotation/attribute is that it is applicable only on string type view model properties and in my case, I am uploading the files via "HttpPostedFileBase" data type view model property. This means that the pre-built data annotation/attribute does not have any means to know the data type of the file(s) that I am uploading which will have  no effect on the limitation that is considered to be applied on the uploaded file type extensions. Of course, there are many other tricks or workarounds to go through while working with the pre-built FileExtensions attribute, but, I prefer the custom data annotation/attribute mechanism, which is much simpler.

So, in the above code, I have created a new class "AllowExtensionsAttribute" (by following the naming convention of custom attribute class) and inherited the ValidationAttribute class. Then, I have created a public property "Extensions" and set the default value with image file type extensions, which means that my custom attribute will accept only image file type to be uploaded. So, in order to allow the required file type extensions, this property will be updated at the time of my custom attribute utilization accordingly. Finally, I have overridden the "IsValid(....)" method which will receive my uploaded file as "HttpPostedFileBase" data type and from this, I will extract the file type extension of the uploaded file and then validate whether it is according to either default file type extension restriction or according to my provided file type extensions.

Step 5
Now, create a new "Models\ImgViewModel.cs" file and replace the following code in it i.e.
//----------------------------------------------------------------------- 
// <copyright file="ImgViewModel.cs" company="None"> 
//     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose. 
// </copyright> 
// <author>Asma Khalid</author> 
//----------------------------------------------------------------------- 
 
namespace ImgExtLimit.Models 

    using System.Collections.Generic; 
    using System.ComponentModel.DataAnnotations; 
    using System.Web; 
    using Helper_Code.Common; 
 
    /// <summary> 
    /// Image view model class. 
    /// </summary> 
    public class ImgViewModel 
    { 
        #region Properties 
 
        /// <summary> 
        /// Gets or sets Image file property. 
        /// </summary> 
        [Required] 
        [Display(Name = "Supported Files .png | .jpg")] 
        [AllowExtensions(Extensions = "png,jpg", ErrorMessage = "Please select only Supported Files .png | .jpg")] 
        public HttpPostedFileBase FileAttach { get; set; } 
 
        /// <summary> 
        /// Gets or sets message property. 
        /// </summary> 
        public string Message { get; set; } 
 
        /// <summary> 
        /// Gets or sets is valid propertty. 
        /// </summary> 
        public bool isValid { get; set; } 
 
        #endregion 
    } 
}

In the above code, I have created my view model which I will attach with my view. Here, I have created HttpPostedFileBase type file attachment property which will capture uploaded image/file data from the end-user, then I have also applied my custom "AllowExtensions" attribute to the FileAttach property and provide the list of file type extensions separated by a comma (,) that I have allowed my system to accept. Then, I have created two more properties; i.e., Message of data type string and isValid of data type Boolean for processing purpose.

Step 6

Create a new "Controllers\ImgController.cs" file and add the following code to it.
//----------------------------------------------------------------------- 
// <copyright file="ImgController.cs" company="None"> 
//     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose. 
// </copyright> 
// <author>Asma Khalid</author> 
//----------------------------------------------------------------------- 
 
namespace ImgExtLimit.Controllers 

    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
    using System.Web.Mvc; 
    using Models; 
 
    /// <summary> 
    /// Image controller class. 
    /// </summary> 
    public class ImgController : Controller 
    { 
        #region Index view method. 
 
        #region Get: /Img/Index method. 
 
        /// <summary> 
        /// Get: /Img/Index method. 
        /// </summary>         
        /// <returns>Return index view</returns> 
        public ActionResult Index() 
        { 
            // Initialization/ 
            ImgViewModel model = new ImgViewModel() { FileAttach = null, Message = string.Empty, isValid = false }; 
 
            try 
            { 
            } 
            catch (Exception ex) 
            { 
                // Info 
                Console.Write(ex); 
            } 
 
            // Info. 
            return this.View(model); 
        } 
 
        #endregion 
 
        #region POST: /Img/Index 
 
        /// <summary> 
        /// POST: /Img/Index 
        /// </summary> 
        /// <param name="model">Model parameter</param> 
        /// <returns>Return - Response information</returns> 
        [HttpPost] 
        [AllowAnonymous] 
        [ValidateAntiForgeryToken] 
        public ActionResult Index(ImgViewModel model) 
        { 
            try 
            { 
                // Verification 
                if (ModelState.IsValid) 
                { 
                    // Settings. 
                    model.Message = "'" + model.FileAttach.FileName + "' file has been successfuly!! uploaded"; 
                    model.isValid = true; 
                } 
                else 
                { 
                    // Settings. 
                    model.Message = "'" + model.FileAttach.FileName + "' file is not supported. "; 
                    model.isValid = false; 
                } 
            } 
            catch (Exception ex) 
            { 
                // Info 
                Console.Write(ex); 
            } 
 
            // Info 
            return this.View(model); 
        } 
 
        #endregion 
 
        #endregion 
    } 
}

In the above code, I have created a GET "Index(...)" method which will initialize the view model with default values and send it to the view page. Finally, I have created a POST "Index(...)" method which will receive an input image file from the end-user, then validate the view model for allowed file type extensions and then send the response message accordingly.

Step 7
Now, create a view "Views\Img\Index.cshtml" file and add the following code to it.
@using ImgExtLimit.Models 
 
@model ImgExtLimit.Models.ImgViewModel 
 
@{ 
    ViewBag.Title = "ASP.NET MVC5: Limit Upload File Extension"; 

 
 
<div class="row"> 
    <div class="panel-heading"> 
        <div class="col-md-8"> 
            <h3> 
                <i class="fa fa-file-text-o"></i> 
                <span>ASP.NET MVC5: Limit Upload File Extension</span> 
            </h3> 
        </div> 
    </div> 
</div> 
 
<br /> 
 
<div class="row"> 
    <div class="col-md-6 col-md-push-2"> 
        <section> 
            @using (Html.BeginForm("Index", "Img", FormMethod.Post, new { enctype = "multipart/form-data", @class = "form-horizontal", role = "form" })) 
            { 
                @Html.AntiForgeryToken() 
 
                <div class="well bs-component"> 
                    <br /> 
 
                    <div class="row"> 
                        <div class="col-md-12"> 
                            <div class="col-md-8 col-md-push-2"> 
                                <div class="input-group"> 
                                    <span class="input-group-btn"> 
                                        <span class="btn btn-default btn-file"> 
                                            Browse… 
                                            @Html.TextBoxFor(m => m.FileAttach, new { type = "file", placeholder = Html.DisplayNameFor(m => m.FileAttach), @class = "form-control" }) 
                                        </span> 
                                    </span> 
                                    <input type="text" class="form-control" readonly> 
                                </div> 
                                @if (Model.isValid && !string.IsNullOrEmpty(Model.Message)) 
                                { 
                                    <span class="text-success">@Model.Message</span> 
                                } 
                                else 
                                { 
                                    <span class="text-danger">@Model.Message</span>@Html.ValidationMessageFor(m => m.FileAttach, "", new { @class = "text-danger" }) 
                                } 
                            </div> 
                        </div> 
                    </div> 
 
                    <div class="form-group"> 
                        <div class="col-md-12"> 
                        </div> 
                    </div> 
 
                    <div class="form-group"> 
                        <div class="col-md-offset-5 col-md-10"> 
                            <input type="submit" class="btn btn-danger" value="Upload" /> 
                        </div> 
                    </div> 
                </div> 
            } 
        </section> 
    </div> 
</div> 
 
@section Scripts 

    @*Scripts*@ 
    @Scripts.Render("~/bundles/bootstrap-file") 
 
    @*Styles*@ 
    @Styles.Render("~/Content/Bootstrap-file/css") 
}


In the above code, I have created a simple view for uploading the image file to the server which will validate the allowed file type extensions at the server side.

Step 8
Now, execute the project



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Fix Bundles Are Not Working After Hosting To MVC Application?

clock December 18, 2018 10:38 by author Peter

If your bundles are not getting configured properly in your server, I have fixed this issue, and here I am going to share with you how you can also fix this error. I hope you will like this.

Background

Recently, I hosted one of my MVC applications to Microsoft Azure cloud. And we usually publish our application in release mode, right? So here comes the problem. You can replicate the same issue in your local machine itself. Just make the debug attribute to false in your Web.config as follows.

  1. <compilation debug="false" targetFramework="4.5" />  

And when you run, you will get a prompt as follows.

Run without debugging

Just select Run without debugging option. Now once after your application is run, you can see some script errors in your browser console saying that the references are not loaded correctly.

Release more error in console

And finally I found the solution. Here we will see that.

"Bundles Are Not Working After Hosting To MVC Application"

As I said, the problem is with your bundle config settings. There are few things you must check before going to the last fix.

  • Please make sure that you have used StyleBundle for creating the style bundle.
  • Please make sure that you have used ScriptBundle for creating the style bundle.
  • Make sure that you are loading the styles using @Styles.Render.
  • Make sure that you are loading the scripts using @Scripts.Render.
  • Make sure that the folder structure is same as you have in local system.
    If none of the above solution works, you can try the last one.
  • Make sure that virtual path of bundles doesn’t contains the folder names you have in your solution.

I will explain it. In my case my bundles were as follows.

@Styles.Render("~/Scripts/JQWidgets/CSS")  
@Scripts.Render("~/Scripts/JQWidgets")  

And I have the folders JQWidgets in my root script folder. This was making the issue.


Folder structure

Now what I did is, I just changed my bundle config settings in BundleConfig.cs as follows(Renaming the folder),

bundles.Add(new ScriptBundle("~/Scripts/Grid")  
bundles.Add(new StyleBundle("~/Scripts/Grid/Styles")  

And I referenced the same bundles as follows in my views.

@Styles.Render("~/Scripts/Grid/Styles")  
@Scripts.Render("~/Scripts/Grid")  

Please try these steps and build your application. Once that is done you can publish your application to cloud. I hope this will solve your issue. Have a happy coding.

Conclusion

Did I miss anything that you may think is needed? Did you find this post useful? I hope you liked this article. Please share with me your valuable suggestions and feedback.

Your turn. What do you think?

A blog isn’t a blog without comments, but do try to stay on topic. If you have a question unrelated to this post, you’re better off posting it on C# Corner, Code Project, Stack Overflow, ASP.NET Forum instead of commenting here. Tweet or email me a link to your question there and I’ll definitely try to help if I can.

HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Stepwise Display Multiple Partial View Using JSON in MVC 5

clock November 9, 2018 10:58 by author Peter

Here are the steps:
Step 1: Create the basic structure of your project, View, multiple partial views View Model,

Step 2: Create your base Controller as in the following,
    public class BaseController: Controller 
    { 
        protected internal virtual CustomJsonResult CustomJson(object json = null, bool allowGet = true) 
        { 
            return new CustomJsonResult(json) 
            { 
                JsonRequestBehavior = allowGet ? JsonRequestBehavior.AllowGet : JsonRequestBehavior.DenyGet 
            }; 
        } 
    } 


It is just small modifications if JSON is not provided handle it. And use this Controller as base controller.

Step 3: Add Class Controller helper which helps you to convert partial view into the string format as in the following,
    public static class ControllerHelper 
    { 
        public static string RenderPartialViewToString(ControllerContext context, string viewName, object model) 
        { 
            var controller = context.Controller; 
            var partialView = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName); 
            var stringBuilder = new StringBuilder(); 
            using(var stringWriter = new StringWriter(stringBuilder)) 
            { 
                using(var htmlWriter = new HtmlTextWriter(stringWriter)) 
                { 
                    controller.ViewData.Model = model; 
                    partialView.View.Render(new ViewContext(controller.ControllerContext, partialView.View, controller.ViewData, new TempDataDictionary(), htmlWriter), htmlWriter); 
                } 
            } 
            return stringBuilder.ToString(); 
        } 
    } 

Step 4: Your action code is below. I have added the 2 partial views. Basically we are converting the partial view with objects into the string format.
    public JsonResult CreatePartialView() 
    { 
        MyMultipleUpdateViewModel obj = new MyMultipleUpdateViewModel(); 
        obj.myTest1ViewModel = new MyTest1ViewModel(); 
        obj.myTest1ViewModel.MyTestUpdate = "Test1" + DateTime.Now.ToString(); 
        obj.myTest2ViewModel = new MyTest2ViewModel(); 
        obj.myTest2ViewModel.MyTestUpdate = "Test2" + DateTime.Now.ToString(); 
        var json = new 
        { 
            Header = "Header", Footer = "Footer" 
        }; 
        return CustomJson(json).AddPartialView("_MyTest1PartialView", obj).AddPartialView("_MyTest2PartialView", obj); 
    } 

Step 5: In View display this JSON data ajax in below way . In below code PartialViewDiv1 and PartialViewDiv2 are two divs in which two partial views will be displayed. I have two partial views you may load more partial views.
    <h2>Index</h2> 
    <script type="text/javascript" src="@Url.Content(" ~/Scripts/jquery-1.10.2.js ")"></script> 
    <script type="text/javascript" src="@Url.Content(" ~/Scripts/jquery.unobtrusive-ajax.min.js ")"></script> 
    <script> 
    function GetData(url, onSuccess) 
    { 
        $.ajax( 
        { 
            type: "GET", 
            cache: false, 
            url: url, 
            dataType: "json", 
            success: function(data, textStatus, jqxhr) 
            { 
                onSuccess(data.Json, data.Html); 
            }, 
            error: function(data, text, error) 
            { 
                alert("Error: " + error); 
            } 
        }); 
        return false; 
    } 
     
    function UpdateDiv(json, html) 
    { 
        $("#PartialViewDiv1").html(html[0]); 
        $("#PartialViewDiv2").html(html[1]); 
    } 
    </script> 
    <input type="button" onclick="GetData('/DisplayMutiplePartialView/CreatePartialView', UpdateDiv);" value="Display Multiple Partial View" /> 
    <br> 
       <br> 
          <div id="PartialViewDiv1"></div> 
       <br> 
       <br> 
          <div id="PartialViewDiv2"></div> 
       <br> 
    <br> 


Step 6: Run application and use URL,
It will appear as below

HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.

 



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Add Robots.txt to your ASP.NET MVC ?

clock October 16, 2018 12:17 by author Peter

One of the items I continuously forgot to add to my web applications is the Robots.txt file that Search Engines use to see what they should index.  This file and site maps help make your site easier to navigate by the bots and allow them to know what's legal and what you would rather not have the published in their engines.  I usually add any administrative pages or account pages despite the fact that they're protected by security, no need for the login page to be index if they sniff the link.

 

So how do you add Robots.txt to your MVC three application?  Glad you asked, here may be a very little code to get you started.

Code

1. Choose the controller you'd wish to use for the robots.txt output.  I selected the HomeController in my application as i use  it for many “top level” generic links like about us, contact us, index, etc.

2. Create a method called Robots to handle the request.
#region -- Robots() Method –
public ActionResult Robots()
{
    Response.ContentType = "text/plain";
    return View();

}
#endregion

Add the Robots.cshtml view to your Controller’s View directory.  Here is the code I have in my view, yours will vary.
@{
    Layout = null;
}
# robots.txt for @this.Request.Url.Host 
User-agent: *
Disallow: /Administration/
Disallow: /Account/

Load up the class you are using to control your routes, if you are in an Area, this could your AreaRegistration class.  If you are at the top like I am and using the standard MVC template, this is probably the Global.asax.cs file.  Add your route to this file, mine looks like this.

routes.MapRoute("Robots.txt",               
"robots.txt",

new { controller = "Home", action = "Robots" });

Now, Compile and test.

If you have an internet facing site, the chances are you will have a bot find you're request this page. you might as well offer them the advantage of the doubt and allow them to know where you want them to travel. additionally you may save yourself some error log once this page is requested and no controller is found.

Just like something in ASP.NET, there are some ways to solve this riddle, if you employ a special approach, please feel free to share it within the comments.

HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.



European ASP.NET MVC 6 Hosting :: ASP.NET MVC 6 Web API Routes and ApiController

clock October 5, 2018 09:47 by author Peter

ASP.NET MVC 6 Web API Project

ASP.NET MVC 6 introduces several new project types after you initially pick that you want to develop an ASP.NET MVC 6 Web Application. One of those application types is the new Web API Project.


If you choose the Web API Project, a new Web API Controller Class is created for you to provide an example of responding to Get, Post, Put, and Delete requests for your API.


public class ValuesController : ApiController {

   // GET /api/values
    public IEnumerable<string> Get() {
        return new string[] { "value1", "value2" };
    }

    // GET /api/values/5
    public string Get(int id) {
        return "value";
    }

    // POST /api/values
    public void Post(string value) {}


    // PUT /api/values/5
    public void Put(int id, string value) {}

    // DELETE /api/values/5
    public void Delete(int id) {}
}


With the Web API Project you will also notice a new API specific route added to the RouteTable in Global.asax.cs.

routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);


Running the project and navigating to ~/api/values will display a list of the values in XML Format. I removed the XML namespacing to keep things simple.

<ArrayOfString>
    <string>value1</string>
    <string>value2</string>
</ArrayOfString>

If you change the Accept Header so that you will only accept JSON, the same controller action will send the values via JSON instead.

["value1","value2"]

Web API Controller Class - ApiController in ASP.NET MVC 4

Creating a new Web API Controller Class is as simple as using the Add Controller Recipe in ASP.NET MVC 4 and choosing the Empty API controller Tempate.



Or, you could just create one via Add Item which has a new Web API Controller Class as an option.


I created a simple ProductsController that handles all the CRUD options for products in a mythical e-commerce website.


public class ProductsController : ApiController {
    private readonly IRepository<Product> _repository;

    public ProductsController(IRepository<Product> repository) {
        _repository = repository;
    }

    public IEnumerable<Product> Get() {
        return _repository.Queryable();
    }

    public Product Get(int id) {
        var product = _repository.Get(id);

        if (product == null)
            throw new HttpResponseException(HttpStatusCode.NotFound);

        return product;
    }

    public HttpResponseMessage<Product> Post(Product product) {
        _repository.Add(product);

        var response = new HttpResponseMessage<Product>
            (product, HttpStatusCode.Created);
        response.Headers.Location = new Uri(Request.RequestUri,
            Url.Route(null, new {id = product.Id}));

        return response;
    }

    public Product Put(int id, Product product) {
        var existingProduct = _repository.Get(id);

        if (existingProduct == null)
            throw new HttpResponseException(HttpStatusCode.NotFound);

        _repository.Save(product);

        return product;
    }

    public HttpResponseMessage Delete(int id) {
        _repository.Delete(id);

        return new HttpResponseMessage(HttpStatusCode.NoContent);
    }
}

You can see that in some instances I am just returning a Product and in other instances I am returning a more informational HttpResponseMessage. For example, in the case of the Post of a new Product, I need to tell the REST Client the new location of the newly added product in the header. In other actions I am also throwing a HttpResponseException if the resource requested is not found. Validation, Logging, and other concerns are being done in various ActionFilters just like in your normal ASP.NET MVC Projects. Try to pull those cross-cutting concerns out of the main logic as much as possible.


ASP.NET Web API OData Syntax for Paging and Querying

If you want to enable various paging and querying of products you can make a slight change to the Get ApiController Action and return an IQueryable<Product> as opposed to IEnumerable<Product>.

public IQueryable<Product> Get() {
    return _repository.Queryable();
}

Now from your browser you can add paging, filtering, sorting, and other options to shape the data. Here is an example call that does paging and sorting.

api/products?$skip=2&$top=2&$orderby=Title

The XML Response by the browser is:

<ArrayOfProduct>
    <Product>
        <Id>3</Id>
        <Title>RipStik</Title>
        <Price>69.00</Price>
    </Product>
    <Product>
        <Id>4</Id>
        <Title>Shred Sled</Title>
        <Price>49.00</Price>
    </Product>
</ArrayOfProduct>


Or the JSON Response:

[{"Id":3,"Price":69.00,"Title":"RipStik"},
{"Id":4,"Price":49.00,"Title":"Shred Sled"}]


Conclusion

ASP.NET Web API integration with ASP.NET MVC 4 is really slick. Now you can easily create an API for your website using the new ApiController Base Class to respond to REST Clients.

 



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Bind Menu And Sub Menu Dynamically In ASP.NET MVC From Database Using LINQ

clock September 21, 2018 11:13 by author Peter

Many times we need to create a menu for a simple application. We ususally get stuck on how to bind the menu. Here in this article we you will learn how to bind menu and sub menu dynamically in ASP.NET MVC from database using linq.

Step 1
I am going to create a database which contains the following fields as well as some dummy data which contains parent & child relationship.
Use the below script to create table & insert query,
    USE [Dynamic_Menu] 
    GO 
    SET ANSI_NULLS ON 
    GO 
    SET QUOTED_IDENTIFIER ON 
    GO 
    SET ANSI_PADDING ON 
    GO 
    CREATE TABLE [dbo].[Menu_List]( 
        [M_ID] [int] IDENTITY(1,1) NOT NULL, 
        [M_P_ID] [int] NULL, 
        [M_NAME] [varchar](50) NULL, 
        [CONTROLLER_NAME] [varchar](50) NULL, 
        [ACTION_NAME] [varchar](50) NULL, 
     CONSTRAINT [PK_Menu_List] PRIMARY KEY CLUSTERED  
    ( 
        [M_ID] ASC 
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY] 
    ) ON [PRIMARY] 
    GO 
    SET ANSI_PADDING OFF 
    GO 
    SET IDENTITY_INSERT [dbo].[Menu_List] ON 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (1, 0, N'My Menu', NULL, NULL) 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (2, 1, N'BCS', N'Menu', N'BCS_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (3, 2, N'Computer', N'Menu', N'Computer_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (4, 1, N'MCS', N'Menu', N'MCS_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (5, 2, N'Maths', N'Menu', N'Maths_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (6, 4, N'Marketing', N'Menu', N'Marketing_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (7, 4, N'Finiance', N'Menu', N'Finiance_Action') 
    SET IDENTITY_INSERT [dbo].[Menu_List] OFF


Step 2
Now create simple MVC appliation using visual studio. After creating project add edmx file by right clicking on project go to Add => New Item => (from right side templates) select Data => Select ADO.NET Entity Data Model => Give proper name to it and click on add button.

Then select your table from database & create .edmx file into your ptoject. After adding the file autmatically connection string will get added into web config file.

Step 3
Now create model as below and add some properties; this model will be used into a controller & view.
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
     
    namespace Dynamic_Menu.Models 
    { 
        public class Menu_List 
        { 
            public int M_ID { get; set; } 
            public int? M_P_ID { get; set; } 
            public string M_NAME { get; set; } 
            public string CONTROLLER_NAME { get; set; } 
            public string ACTION_NAME { get; set; } 
        } 
    } 

Step 4
Now add controller into our application and write below code into it. From action method GetMenuList() we will get data from our database using linq query.
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
    using System.Web.Mvc; 
     
    namespace Dynamic_Menu.Controllers 
    { 
        public class HomeController : Controller 
        { 
            MenuEntities objEntity = new MenuEntities(); 
            public ActionResult Index() 
            { 
                return View();         
            } 
            public ActionResult GetMenuList() 
            { 
                try 
                { 
                    var result = (from m in objEntity.Menu_Tree 
                                  select new Dynamic_Menu.Models.Menu_List 
                                  { 
                                      M_ID = m.M_ID, 
                                      M_P_ID = m.M_P_ID, 
                                      M_NAME = m.M_NAME, 
                      CONTROLLER_NAME = CONTROLLER_NAME, 
                                      ACTION_NAME = ACTION_NAME, 
                                  }).ToList(); 
                    return View("Menu", result); 
                } 
                catch (Exception ex) 
                { 
                    var error = ex.Message.ToString(); 
                    return Content("Error"); 
                }  
            } 
        } 
    }

Step 5
Now create a view for Index action method as like.
    @{ 
        ViewBag.Title = "Index"; 
        Layout = "~/Views/Shared/_Layout.cshtml"; 
    } 
     
    <h2>Index</h2>


Now create layout view for our application. Also create one partial view (name Menu.cshtml) as brlow,  which will render menu tree list when we are going to call action method from our layout page. In this partial view we are getting data into a IEnumerable list format and we are applying some logic as below,

Note
This is just demo / sample application, according to your requirement you can add foreach loop for more hierarchy levels. This is only a two level menu tree strucure.
_Layout.cshtml  =>

    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <meta name="viewport" content="width=device-width" /> 
        <title>@ViewBag.Title</title> 
        @Html.Action("GetMenuList", "Home") 
    </head> 
    <body> 
        <div> 
            @RenderBody() 
        </div> 
    </body> 
    </html>

 Menu.cshtml =>

    @model IEnumerable<Dynamic_Menu.Models.Menu_List> 
    <div> 
        <ul> 
            @{foreach (var item in Model.Where(s => s.M_P_ID == 0).GroupBy(Obj => new { Obj.M_ID }).Distinct().ToList()) 
            { 
                <li> 
                    <a href="#"> 
                        @item.FirstOrDefault().M_NAME 
                    </a> 
                    <ul> 
                        @{foreach (var firstItem in (Model.Where(s => s.M_P_ID == item.FirstOrDefault().M_ID).ToList())) 
                        { 
                            <li> 
                                <a href="#"> 
                                    @firstItem.M_NAME 
                                </a> 
                                <ul> 
                                    @foreach (var secondItem in (Model.Where(s => s.M_P_ID == firstItem.M_ID).ToList())) 
                                    { 
                                        <li> 
                                            <a href="/@secondItem.CONTROLLER_NAME/@secondItem.ACTION_NAME"> 
                                                @secondItem.M_NAME 
                                            </a> 
     
                                        </li> 
                                    } 
                                </ul> 
     
                            </li> 
                        } 
                        } 
                    </ul> 
                </li> 
            } 
            } 
        </ul> 
    </div> 


Step 5
Now create another controller to render views whenever we are clicking on hyper links from menu, it will redirect to that view by using controller name & action name
    namespace Dynamic_Menu.Controllers 
    { 
        public class MenuController : Controller 
        { 
    public ActionResult Computer_Action() 
            { 
                return View(); 
            } 
            public ActionResult Maths_Action() 
            { 
                return View(); 
            } 
            public ActionResult Marketing_Action() 
            { 
                return View(); 
            } 
            public ActionResult Finiance_Action() 
            { 
                return View(); 
            } 
     
     } 
    }


Create some views for above action as like
 
View For Computer_Action as,
    @{ 
        Layout = "~/Views/Shared/_Layout.cshtml"; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <meta name="viewport" content="width=device-width" /> 
        <title>Computer_Action</title> 
    </head> 
    <body> 
        <div>  
            <h2>Welcome To Computer View</h2> 
        </div> 
    </body> 
    </html>

View For MCS_Action as
@{ 
    Layout = "~/Views/Shared/_Layout.cshtml"; 

 
<!DOCTYPE html> 
 
<html> 
<head> 
    <meta name="viewport" content="width=device-width" /> 
    <title>MCS_Action</title> 
</head> 
<body> 
    <div>  
        <h2>Welcome To MCS View</h2> 
    </div> 
</body> 
</html> 


Step 6
Now run the application.
Index view after running the application into a browser.

If we click on menu   then our output will be:

In this article, you learned how to bind menu and sub menu dynamically in ASP.NET MVC from database using linq.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Is MVC Replacing ASP.NET Web Forms?

clock September 18, 2018 09:53 by author Peter

We often think that one technology will be totally replaced by a new release or new version of technology. This article tries to dicuss that and similar issues and I will share my industry experience, not just what I have seen in India (the largest IT Solutions Provider to the world) but also in the USA.

I consider this to be a very hot topic and a good candidate of debate but I will try to share my thoughts on such a burning topic. This article does not highlight or defame any technology, I am just going to provide my perspective as I have seen, experienced and advised to various clients and software teams.

Why new Versions

The principle “Change is Constant” applies very well to the software industry and I respect this overflow of information. Because this gives me reason to “Keep Learning and stay ahead of the Curve”. By saying so I didn't mean that someone must learn anything and everything you can get your hands on. No, certainly not, but before I explain this any further let's take a step back and understand “Why new Versions” keep coming.

We are fortunate that we have seen complete transition of the software industry from Desktop to Web to Mobile, future generations may not witness this great and life changing shift. Also, I recall my days when I was working and studying software in 1995, no one imagined that there will be MVC, WPF, WCF, so many versions of .NET and SQL Server and so on. Industry was happy with Microsoft Access, FoxPro, C, C++ and Oracle and so on. But our needs keep changing, they evolved and then shell is broken to have huge expansion and today we have many kinds of software technology and server products from client-side to server-side to mobile and hand-held and many more. We moved from on premise to the Cloud and Machine Learning is helping to dictate patterns and suggest needs.

This is why software companies keep building the latest and newest technologies to enable and empower the world to build for the future. When they release a version of a technology or language and they discover some issues or new features in that then they release newer versions and this in a chain-reaction process and it will not stop.

Oh, then I will die Learning

As per Darwin's Evolution Theory “Survival of the Fittest”, "fit" refers to "best adapted to the current environment". Here you simply replace environment with the software industry. I am one of you and I am not saying that everyone must learn everything but what I suggest is to stick to your technology of choice and have good knowledge of the offered tools and technologies and various versions and when to use which one.

Also, you don't necessarily need to understand every single thing. For example, I only focus on .NET and related technologies, if anything falls beyond this area then I am not bothered. To be more precise, I don't understand Microsoft CRM, SharePoint, System Center, SQL Server Database Administration and few more things like that.

But this is not my weak point because “I continue to build my .NET Muscle” and continue to learn about what helps me build Enterprise solutions using Microsoft .NET.

So choose your area of interest and where you have invested and then keep learning in a similar field and then you will no longer find it challenging because if you observe, new versions come after every few years and that must be otherwise it will be no fun!

Hmm, so Isn't MVC Replacing ASP.NET Web Forms

Such decisions are not final and have no concrete answers. Yes, the industry changes their needs and so new technologies such as MVC and WPF takes over. This definitely doesn't mean that ASP.NET Web Forms is replaced or it's dead. If you understand the Microsoft Web fundamentals, MVC is based on ASP.NET and industry is trying to shift as and when they can from Web Forms to MVC and reap the benefits it offers.

Did you know that MVC is much older than ASP.NET? Yes, ASP.NET 1.0 was released in 2002 and MVC was created in 1979 originally named as “Thing-Model-View-Controller” but later simplified to be known as MVC.

In my view I consider that there are now two technologies to build Web Solutions using Microsoft and based on your needs you can pick one that works well for you. Usually such technology selections are made by architects assigned to the project.

So there is no such Golden Rule that every new or existing application must be either created using MVC or migrated to MVC because MVC is the latest and future the of web. Though it is.

Architectural Thinking: Brownfield Vs Greenfield Applications

All software applications you have worked or will work in future are either Brownfield or Greenfield.

  • Brownfield Development: When any existing or legacy applications need to have new features or changes to address business needs, it is known as brownfield. In such situations, unless you are building a new module or component, you have less, limited or no scope to use new architectural styles, patterns and so on. The very reason of such limitations is because those old applications are built using an old version of technologies and the latest versions of one technology/framework and many are not be compatible with old versions.
  • Greenfield Development: When a brand-new project is being envisioned and no previous work is done in that or a related area then it's called Greenfield. In the software industry it doesn't happen very often. But whenever it happens its the architect's responsibility to determine what the best technology is to address business needs.

Hence, it's not appropriate to say that because MVC is so new hence every new web application must be made using MVC or if WPF is available in addition to Windows Forms so every desktop application must be made using WPF. Whatever is the case neither ASP.NET Web Forms nor Windows Forms can be totally ignored.

Why and Why not the Latest Technologies should be chosen

First the reasons why not.

  1. It's Brownfield and new technology doesn't fit anywhere.
  2. If new technology or versions are introduced then it will cause many build errors due to outdated references of non-supported library references.
  3. Business goals and software quality are not compromised by continuing to use current and available technologies like ASP.NET Web Forms over MVC or Windows Forms over WPF.
  4. You are not investing money in any extra off-the-shelf tools to handle issues that could have been handled by the latest versions of similar area of technologies, for example MVC instead of ASP.NET Web Forms, or WPF over Windows Forms.
  5. Teams often might not have a certain skill set that allows them to proceed with development using new technology options
  6. Budget allocation from a client often may impact your decision to use and develop using the latest technologies.
  7. If the core/bestselling features of a new candidate technology (MVC or WPF) are not being used at least up to 50% then you have done nothing.
  8. Considering how soon the client and business wants to have an application ready, it turns being a major factor to dictate the technology of choice.
  9. The client and business doesn't care how you do it; what matters is the end-result and a workable / good-enough software.
  10. No way to use old legacy downstream applications with the latest available technologies.

Why develop using Latest Technologies

  1. Greenfield software solution and no legacy or old piece of code is being used.
  2. Focus is more on Robustness, Testability, Object Oriented design and quality. (This doesn't mean previous technology can't accomplish these; it's about ease and in-built features and offerings).
  3. Amazing team with great skills to learn new technologies and adapt the changes.
  4. Company's vision is to showcase products build using latest technologies.
  5. Client themselves want the solution to be developed using latest technologies and have budget to support that.

Why MVC over ASP.NET Web Forms then

Note: this section assumes that you are aware of MVC benefits and the general technical terms used below.

  1. Separation of Concerns is the core of MVC.
  2. Single Responsibility Principle is done by default.
  3. Unified and even better framework to work on WebAPI, Mobile, HTML 5, CSS3, Security and Deployment (including Azure).
  4. Unit testing is easily done to have stable, robust and quality software solutions delivered continuously.
  5. Fast screen generation for CRUD operations via Scaffolding.
  6. Convention over configuration.

Summary
Based on my experience as an architect in the industry I would like to summarize that it's very hard for any organization to keep up with the latest version and technologies all the time because by the time you become comfortable with one version the newer is around the corner. So if you are working on MVC 4, then see if you can learn and try some application being developed on your own. Or if you just happen to be in the ASP.NET Web Forms world until now then I would encourage you to try converting that application to MVC for your personal benefit. This will force you to learn new technology and apply that learning. If you have made some progress in that then in the next interview you can proudly showcase your MVC knowledge and say that you have migrated ASP.NET Web Forms to MVC.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in