European ASP.NET MVC Hosting

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

ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Output Caching in MVC

clock June 16, 2021 09:09 by author Peter

The main purpose of using Output Caching is to dramatically improve the performance of an ASP.NET MVC Application. It enables us to cache the content returned by any controller method so that the same content does not need to be generated each time the same controller method is invoked. Output Caching has huge advantages, such as it reduces server round trips, reduces database server round trips, reduces network traffic etc.

 
Keep the following in mind:
    Avoid caching contents that are unique per user.

    Avoid caching contents that are accessed rarely.

    Use caching for contents that are accessed frequently.

Let's take an example. My MVC application displays a list of database records on the view page so by default each time the user invokes the controller method to see records, the application loops through the entire process and executes the database query. And this can actually decrease the application performance. So, we can advantage of the "Output Caching" that avoids executing database queries each time the user invokes the controller method. Here the view page is retrieved from the cache instead of invoking the controller method and doing redundant work.
Cached Content Locations
 
In the above paragraph I said, in Output Caching the view page is retrieved from the cache, so where is the content cached/stored?
 
Please note, there is no guarantee that content will be cached for the amount of time that we specify. When memory resources become low, the cache starts evicting content automatically.
 
OutputCache label has a "Location" attribute and it is fully controllable. Its default value is "Any", however there are the following locations available; as of now, we can use any one.
 
1. Any   2. Client   3. Downstream   4. Server   5. None   6. ServerAndClient
 
With "Any", the output cache is stored on the server where the request was processed. The recommended store cache is always on the server very carefully. You will learn about some security related tips in the following "Don't use Output Cache".
 
How Output Cache Works
It is very important to understand how the "Output Cache" works. Anyone who invokes a controller method will get the same cached version of the view page. This means that the amount of work that the web server must perform to serve the view page is dramatically reduced.
 
For example, I have recorded a GIF here to show you how the same request is being made from three different clients (here three different browsers) and we are getting the same cached version (look at the time).

Okay, now let's look at the code, how I developed the one above, how to make any controller action or method cacheable. Here it is
[OutputCache(Duration = 10, VaryByParam = "name")]
 
Just add the preceding label before the controller method. The duration is in seconds, 10 seconds here. If you don't provide a "Duration" value then the default will be used, 60 seconds. I am using VaryByParam="name" and "VeryByParam" is something that makes many differences that you should care about that will be discussed later. "name" is a parameter passed by the user with the request to do database records filering.
 
Here is the complete code:
    [HttpPost]  
        [OutputCache(Duration = 10, VaryByParam = "name")]  
        public ActionResult SearchCustomer(string name = "")  
        {  
            NorthwindEntities db = new NorthwindEntities();  
            var model = from r in db.Customers  
                        where r.ContactName.Contains(name)  
                        select r;  
            if (model.Count() > 0)  
            {  
                return View(model);  
            }  
            else  
            {  
                return View();  
            }  
        }  


In the code above, I'm looking at the "name" parameter passed by the user and then, depending on the name, selecting matching records with a LINQ query and then checking if the model has the number of records greater than zero then send the model to the view else simply send the view (no model).
VaryByParam can be one of the following types:

1. VaryByParam = "none": Think of it like, we don't want to care about the form parameter or query string parameter passed by the user from the view page. If I use "none" then it will create the same cached version of the content for every user who visits the website, and the content will only change after a specified number of seconds (here 10 seconds).

Let's use [OutputCache(Duration = 10, VaryByParam = "none")] in the code above and look at the behavior.

In above GIF you can notice on second request to see list of records that contains "a" nothing happens, because it is displaying the cached data.
2. VaryByParam = "name": This property enables you to create different cached versions of the content when a form parameter or query string parameter varies. In other words if I find records matching "ce" string then a new cache will be created by replacing the older one, again if I find records matching "ab" string then a new cache will be created by replacing the last one ("ce" cached), no matter duration is elapsed or not.
 
Let's use [OutputCache(Duration = 10, VaryByParam = "name")] in code above and look at behavior.

In the above GIF note that on each new request with a different query string parameter or form parameter, a new cache is being created; look at the time it is changing. Here the use of the cache is that if I request the same thing that I requested previously then the cached version will be rendered, here it is:

In the above GIF note that nothing happens (look at the time) when I continuously request the same information, rendering the cached version.
3. VaryByParam = "*": We can use * for all parameters or a semi-colon separated list to cache various versions. This works very similar to the one above (VaryByParam="name").
    [OutputCache(Duration = 10, VaryByParam = "*")]  
    public ActionResult SearchCustomer(string name = "", string city = "")  
    {  
        NorthwindEntities db = new NorthwindEntities();  
        ...  

OR
    [OutputCache(Duration = 10, VaryByParam = "name; city")]  
    public ActionResult SearchCustomer(string name = "", string city = "")  
    {  
        NorthwindEntities db = new NorthwindEntities();  
        ...  

Both scenarios work the same, so use whichever one that makes you happy.
Check Web Page is Cache-able or not?
 
Fiddler is a great tool if you want to check whether a requested web page is cache-able or not, here is a GIF image of it.

In the above GIF you can see the GET request is not cacheable whereas the POST request is cacheable and with max-age: 10 seconds.
Don't use Output Cache
 
Here you will learn about some quick security related issues and their prevention.

Danger 1
We should always be careful while using "OutputCache", I will show you an example here. Let's look at the following controller action method and try finding security vulnerabilities.
    [OutputCache(Duration = 10, VaryByParam = "none")]  
        public ActionResult Profiles()  
        {  
            if (User.Identity.IsAuthenticated)  
            {  
                MembershipUser u = Membership.GetUser(User.Identity.Name);  
                ViewBag.welcomeNote = "Welcome back " + User.Identity.Name + ". Your last login date was " + u.LastLoginDate;  
            }  
            else  
            {  
                ViewBag.welcomeNote = "Welcome Guest";  
            }  
            return View();  
        }  
       


Now, I'm running the code above, see how the usernames are appearing in both (IE and Chrome) browsers, the GIF is given below. Username is also being cached and stored on the server for other users.

In the above controller action method we don't have a "VaryByCustom" or "Location" attribute with "OutputCache" to safeguard it, so by default it uses Location = OutputCacheLocation.Any that is dangerous in this case. If you are using membership in the web application then you should pay special attention. A few ways are given below, the first is more secure and recommendable.

1st Way
You can also take advantage of the VaryByCustom property in [OutputCache] by overriding HttpApplication.GetVaryByCustomString and checking HttpContext.Current.User.IsAuthenticated.

This is what I will create in the Global.asax.cs file:
    public override string GetVaryByCustomString(HttpContext context, string custom)  
    {  
        if (custom == "LoggedUserName")  
        {  
            if (context.Request.IsAuthenticated)  
            {  
                return context.User.Identity.Name;  
            }  
            return null;  
        }  
        return base.GetVaryByCustomString(context, custom);  
    }  


And then use it in the OutputCache attribute:
    [OutputCache(Duration = 10, VaryByParam = "none", VaryByCustom = "LoggedUserName")]  
    public ActionResult Profiles()  
    {  
        //...  
    }  

Now for every user logged in on the website OutputCache will create a separate version, and it works great. We can even use Duration, VaryByParam, VaryByCustom and Location attributes together to make it more productive, useful and secure.

We can also enable separate cache entries for each browser, VaryByCustom can be set to a value of "browser". This functionality is built into the caching module, and will insert separate cached versions of the page for each browser name and major version. You don't need to override HttpApplication.GetVaryByCustomString.
    [OutputCache(Duration = 10, VaryByParam = "none", VaryByCustom = "browser")]  
    public ActionResult Profiles()  
    {  
       ...  


2nd Way
See, this is less reliable but works. You should use Location = OutputCacheLocation.Client. If you don't, the login username will also be cached and stored on the server for other users and that is confusing & quite dangerous.

Here is the complete controller action method code.
    [OutputCache(Duration = 10, VaryByParam = "none", Location = OutputCacheLocation.Client)]  
    public ActionResult Profiles()  
    {  
        ...  
    }  

Note 1: POST requests are not cached on the client, in other words this will not work because it is a POST request and the caching location is on the client.
      [HttpPost]  
    [OutputCache(Duration = 10, VaryByParam = "name", Location = OutputCacheLocation.Client)]  
    public ActionResult SearchCustomer(string name = "")  
    {  
        ...  
    }  


Note 2: If you are trying to test client-side caching (like the one given above) and hitting F5 then you are losing the client cache. The way the client cache is supposed to work is that you have links on the site pointing to the Client action from some other views and when the user clicks on those links the cached version will be served.

Danger 2
If you want a more secure application then you should only enable caching for a page when the page does not require authorization. Normally, you require authorization for a page when you display personalized data in the page. Since you don't want personalized data to be shared among multiple users, don't cache pages that require authorization.
    [Authorize]  
    [OutputCache(Duration = 10, VaryByParam = "none")]  
    public ActionResult CreditCardDetails()  
    {  
        ...  
    }  


In the code above, you are combining OutputCaching and Authorize with an action method that contains your credit card information. And you know how OutputCaching stores data out of the database that is not as secure as a database. So you are broadcasting your private information to the entire world. Don't do it.

Creating Cache Profile
It is very difficult to change the rules (like Duration, VaryByParam, VaryByCustom, Location) used with "OutputCache" on each controller method when your large application has already been deployed.

So, there is an alternative to configure the OutputCache profile in the web.config file. By configuring output caching in the web configuration file, you can control it on one central location. You can create one cache profile and apply the profile to several controllers or controller actions. Also, you can modify the web configuration file without recompiling your application. Any changes to the web configuration file will be detected automatically and applied to the entire application.

In the following code you can see I have used a new attribute CacheProfile that maps to Cache10Seconds that is in web.config.
    [OutputCache(CacheProfile = "Cache10Seconds", VaryByCustom = "LoggedUserName")]  
    public ActionResult Profiles()  
    {  
       ...  

And then web.config:
    <system.web>  
      <caching>  
        <outputCacheSettings>  
            <outputCacheProfiles>  
                <add name="Cache10Seconds" duration="10" varyByParam="none"/>  
            </outputCacheProfiles>  
        </outputCacheSettings>  
      </caching>  
      ...  


Please note, I moved Duration, VaryByParam and Location (we can use it also) in web.config but not VaryByCustom and the reason is, it is used for overriding the rules.
Now, assume for any reason I want to disable caching for an entire application that has already been deployed to production, then you can simply modify the cache profiles defined in the web configuration file.
 
We can even disable it as in the following:

    <system.web>  
        <caching>  
            <outputCache enableOutputCache="false" =""/>  
            <outputCacheSettings>  
                  <outputCacheProfiles>  
                        <add name="Cache10Seconds" duration="10" varyByParam="none"/>                 
          </outputCacheProfiles>           
        </outputCacheSettings>  
      </caching>  

This approach is pretty good because rather than targeting any specific outputCacheProfile we can disable all at once, awesome.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Create Simple Web API In ASP.NET MVC

clock March 26, 2021 08:32 by author Peter

This article explains how to access data from a view to the controller's action method. The action method is a simple C# method that can be parameterized or without a parameter in the controller. We use two types of methods to handle our browser request; one is HTTP GET and another is HTTP POST. When we call an action method by a request's URL by the browser then the HTTP GET method will be called but when a request is from a button click event then the HTTP POST method will be called. So in this article, I am going to explaining how to access view input field data in the controller's action method when a HTTP POST request is called.

 
To understand how to access view input field data in the controller's action method (POST), we create a "Calculate Simple Interest" application. This application gets Principle, Rate and Time as user input and generates simple interest. So let's proceed with the application.
 
Create an action method in the CalculateSimpleInterest controller (CalculateSimpleInterestController.cs) that renders the view on the UI.
    public ActionResult SimpleInterest()  
    {  
        return View();  
    }  

Create a view to get user input from the UI, so the code is:
    <h2>Calculate Simple Interest</h2>  
    <fieldset>  
            <legend>Calculate Simple Interest</legend>  
        @using (Ajax.BeginForm("CalculateSimpleInterestResult","CalculateSimpleInterest",  
                                new AjaxOptions { UpdateTargetId = "divInterestDeatils" }))  
        {  
            <div id="divInterestDeatils"></div>  
            <ol>  
                <li>  
                    @Html.Label("Amount")  
                    @Html.TextBox("txtAmount")  
                </li>  
                <li>  
                    @Html.Label("Rate")  
                    @Html.TextBox("txtRate")  
                </li>  
                <li>  
                    @Html.Label("Year")  
                    @Html.TextBox("txtYear")  
                </li>  
            </ol>  
        <button>Calculate</button>  
        }     
    </fieldset>  


So now the screen is ready to get input and it shows it as:

 

Figure 1.1 Input screens to calculate simple interest

I will now explain the four ways to get the view's data in the controller action. These are:
    Using Traditional approach
    Using the FormCollection Object
    Using the Parameters
    Strongly type model binding to view

Using Traditional Approach
In the traditional approach we use the request object of the HttpRequestBase class. The request object has view input field values in name/value pairs. When we create a submit button then the request type POST is created and calls the POST method.

Figure 1.2 Requested Data

We have four data, those are in Name-Value pairs. So we can access these data in a POST method by passing the Name as an indexer in the Request and get values. Our POST method means the controller action that handles the POST request type is [HttpPost].
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult()  
    {  
        decimal principle = Convert.ToDecimal(Request["txtAmount"].ToString());  
        decimal rate = Convert.ToDecimal(Request["txtRate"].ToString());  
        int time = Convert.ToInt32(Request["txtYear"].ToString());  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  


When it executes, we get simple interest as the result as in the following:

Figure 1.3 Output screen after getting response

Using the FormCollection Object
We can also get post requested data by the FormCollection object. The FormCollection object also has requested data in the name/value collection as the Request object. To get data from the FormCollection object we need to pass it is as a parameter and it has all the input field data submitted on the form.
    [HttpPost]  
      
    public ActionResult CalculateSimpleInterestResult(FormCollection form)  
    {  
        decimal principle = Convert.ToDecimal(form["txtAmount"].ToString());  
        decimal rate = Convert.ToDecimal(form["txtRate"].ToString());  
        int time = Convert.ToInt32(form["txtYear"].ToString());  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }


It also gives the same output as Figure 1.3 shows.
 
Using the Parameters

We can pass all input field names as a parameter to the post action method. The input field name and parameter name should be the same. These parameters have input field values that were entered by the user. So we can access view input field values from these parameters. The input field takes a string value from the user so the parameter should be a string type. There is no need to define a parameter in any specific sequence.
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult(string txtAmount, string txtRate, string txtYear)  
    {  
        decimal principle = Convert.ToDecimal(txtAmount);  
        decimal rate = Convert.ToDecimal(txtRate);  
        int time = Convert.ToInt32(txtYear);  
       
        decimal simpleInteresrt = (principle*time*rate)/100;  
       
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + principle+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + time + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  


It also gives the same output as Figure 1.3 shows.
 
In all three approaches above we are parsing the string to a non-string type. If any of the parsing attempts fail then the entire action will fail. We are converting each value to avoid an exception but it also increases the amount of code. So we look at the fourth approach that would reduce the amount of code.
 
Strongly type model binding to view
 
We bind a model to the view; that is called strongly type model binding.
 
Step 1
Create a Model for Simple Interest
    namespace CalculateSimpleInterest.Models  
    {  
        public class SimpleInterestModel  
        {  
            public decimal Amount { get; set; }  
            public decimal Rate { get; set; }  
            public int Year { get; set; }  
        }  
    }  


Step 2
Create an action method that render a view on the UI
 
We are passing an empty model to be bound to the view.
    public ActionResult SimpleInterest()  
    {  
        SimpleInterestModel model = new SimpleInterestModel();  
        return View(model);  
    }  


Step 3
Create a strongly typed view that has the same screen as in Figure 1.1
    @model CalculateSimpleInterest.Models.SimpleInterestModel  
       
    @{  
        ViewBag.Title = "SimpleInterest";  
    }  
       
    <h2>Calulate Simple Interest</h2>  
       
    @using (Ajax.BeginForm("CalculateSimpleInterestResult","CalculateSimpleInterest",  
                                new AjaxOptions { UpdateTargetId = "divInterestDeatils" }))  
        {  
             
        <fieldset>  
            <legend>Calulate Simple Interest</legend>  
            <div id="divInterestDeatils"></div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Amount)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Amount)            
            </div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Rate)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Rate)            
            </div>  
       
            <div class="editor-label">  
                @Html.LabelFor(model => model.Year)  
            </div>  
            <div class="editor-field">  
                @Html.EditorFor(model => model.Year)             
            </div>  
            <p>  
                <input type="submit" value="Calculate" />  
            </p>  
        </fieldset>  
    }  
       
    @section Scripts {  
        @Scripts.Render("~/bundles/jqueryval")  
    }  

Step 4
Create an action method that handles the POST request and processes the data
 
In the action method we pass a model as the parameter. That model has UI input field data. Here we do not need to parse and do not need to write extra code.
    [HttpPost]  
    public ActionResult CalculateSimpleInterestResult(SimpleInterestModel model)  
    {  
        decimal simpleInteresrt = (model.Amount*model.Year*model.Rate)/100;  
        StringBuilder sbInterest = new StringBuilder();  
        sbInterest.Append("<b>Amount :</b> " + model.Amount+"<br/>");  
        sbInterest.Append("<b>Rate :</b> " + model.Rate + "<br/>");  
        sbInterest.Append("<b>Time(year) :</b> " + model.Year + "<br/>");  
        sbInterest.Append("<b>Interest :</b> " + simpleInteresrt);  
        return Content(sbInterest.ToString());  
    }  

It also gives the same output as Figure 1.3 shows.



ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: HTTP Error 404.0 0 Not Found in MVC

clock January 29, 2021 08:32 by author Peter

The Resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I saw this error today while working on a MVC Web Project, this is a common error we get while running websites and performing any CRUD (Create, Read, Update, Delete) operation. The Stackoverflow forum is full of such queries so I decided to describe the fix here. You might not find it useful for your case but I think the majority of requests can be satisfied.

 
Let me show you an error page image here:


Look at the URL in the above image. The URL is requesting a view/page to edit the record but unfortunately the page is not found. Actually the page/view is already there but the problem is, we are not supplying the correct ID or say index to edit.
In other words we need an URL something like http://localhost:25349/demo/Edit/1 to edit the first record and http://localhost:25349/demo/Edit/2 to edit the second record. Yet in the preceding image we are not supplying the ID.
 
Let's fix it. Open the "Index" view of the "demo" controller and look at the existing code:


Oh! there is a comment instead of the ID parameter, so once you change it, such as in the following:
    <td>  
        @Html.ActionLink("Edit", "Edit", new { id=item.SM_UID }) |  
        @Html.ActionLink("Details", "Details", new { id=item.SM_UID }) |  
        @Html.ActionLink("Delete", "Delete", new { id=item.SM_UID })  
    </td>  


Your application will work fine.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Ajax.ActionLink and Html.ActionLink in MVC

clock December 16, 2020 08:26 by author Peter

In this article, you will learn the use of the Ajax.ActionLink helper and Html.ActionLink. I will compare both to show you how they differ. Okay, let's begin with Html.ActionLink.

Html.ActionLink
Html.ActionLink creates a hyperlink on a view page and the user clicks it to navigate to a new URL. It does not link to a view directly, rather it links to a controller's action. Here are some samples of Html.ActionLink.
 
If you want to navigate to the same controller's action method, use the one given below. Razor is smart enough to assume the first param is link text and the second param is the action method name, if it finds only two parameters.
    @Html.ActionLink("Click here", // <-- Link text  
                     "Index" // <-- Action Method Name  
                     )  

It's rendered HTML: <a href="/">Click here</a>
 
If you want to navigate to a different controller's action method, use the one given below. You can even avoid typing "null" for the route value and htmlArguments. Here also, razor will assume the first param as link text, the second param as the action method name and the third param as the controller name, if it finds three parameters.
    @Html.ActionLink("Click here", // <-- Link text  
                     "About", // <-- Action Method Name  
                     "Home", // <-- Controller Name  
                     null, // <-- Route value  
                     null // <-- htmlArguments  
                     )  


It's rendered HTML: <a href="/Home/About">Click here</a>
 
If you want to navigate to the same controller's action method then use the one given below. Here razor will assume the first param is link text, second param is an action method and the third param is the route value. We can avoid typing "null" for the htmlArgument; that works fine.
    @Html.ActionLink("Edit", // <-- Link text  
                     "Edit", // <-- Action Method Name  
                     new { id=item.CustomerID }, // <-- Route value  
                     null // <-- htmlArguments  
                    )  


It's rendered HTML: <a href="/Home/Edit/187">Edit</a>
 
If you want to navigate to the same controller's action method then use the one given below. Here razor will assume the first param is link text, second param is the action method and the third param is the route value. Instead of typing "null" or avoiding the htmlAttribute, I am using the "class" attribute with "ui-btn" as the name.
    @Html.ActionLink("Edit", // <-- Link text  
                     "Edit", // <-- Action Method Name  
                     new { id=item.CustomerID }, // <-- Route value  
                     new {@class="ui-btn"} // <-- htmlArguments  
                    )  

It's rendered HTML: <a class="ui-btn" href="/Home/Edit/187">Edit</a>
 
What if one wants rendered HTML to be as given below that is an application-specific anonymous attribute:
<a class="ui-btn" data-val="abc" href="/Home/Edit/ANTON">Edit</a>
 
If you try to do it as given below, you will get the error:

The reason is that we can't use an anonymous property/attribute having a dash in the name. Use an underscore instead of a dash and MVC will automatically replace the underscore with a dash in the rendered HTML, here it is:
    @Html.ActionLink("Edit", // <-- Link text  
                     "Edit", // <-- Action Method Name  
                     new { id=item.CustomerID }, // <-- Route arguments  
                     new {@class="ui-btn", data_val="abc"} // <-- htmlArguments  
                    )  

That's how we work around in MVC for any anonymous property.
 
Note: You can notice that Html.ActionLink takes at least two parameters as Html.ActionLink(LinkText, ActionMethod).
 
Ajax.ActionLink

Ajax.ActionLink is much like the Html.ActionLink counterpart, it also creates the hyperlink <a href="">Click here</a> but when the user clicks it and has a JavaScript enabled browser, Ajax.ActionLink sends the asynchronous request instead of navigating to the new URL. With the Ajax.ActionLink we specify what controller's action method is to be invoked and also specify what to do with the response coming back from the action method.
 
Let's create an Ajax.ActionLink helper that will send an asynchronous request to the action method and will update the DOM with the result.
 
Step 1
At first we need an Ajax.ActionLink that will send the async request, so here we go:
    <h2>Customers</h2>  
    @Ajax.ActionLink("Customer from Germany", // <-- Text to display  
                     "Germany", // <-- Action Method Name  
                     new AjaxOptions  
                     {  
                         UpdateTargetId="CustomerList", // <-- DOM element ID to update  
                         InsertionMode = InsertionMode.Replace, // <-- Replace the content of DOM element  
                         HttpMethod = "GET" // <-- HTTP method  
                     })  
    @Ajax.ActionLink("Customer from Mexico", // <-- Text to display  
                     "Mexico", // <-- Action Method Name  
                     new AjaxOptions  
                     {  
                         UpdateTargetId="CustomerList", // <-- DOM element ID to update  
                         InsertionMode = InsertionMode.Replace, // <-- Replace the content of DOM element  
                         HttpMethod = "GET" // <-- HTTP method  
                     })  
    <div id="CustomerList"></div>  
    @section scripts{  
        @Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")  
    }  


In the code above, you can see that I have created two Ajax.ActionLinks, one to display the list of customers from Germany and another to display the list of customers from Mexico, all will be called asynchronously. We have not specified which controller to access, so by default it will look in the same controller. Here is the generated HTML by both Ajax.ActionLink.
<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#CustomerList" href="/Home/Germany">Customer from Germany</a>
 
<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#CustomerList" href="/Home/Mexico">Customer from Mexico</a>
 

The unobtrusive jQuery uses the data-ajax prefix for JavaScript to invoke action methods on the server rather than intrusively emitting inline client scripts.
 
When we will click the link it will make a GET HTTP method call and the returned result will be updated to a DOM element by Id "CustomerList".
 
Always remember to place a reference of the jquery.unobtrusive-ajax.js library file after jquery-{version}.js file references, we can use bundling also. If you don't include the jquery.unobtrusive-ajax.js or do it incorrectly, then when you click the link to the view list of countries, an async result will be opened on the new browser tab.
 
Also, ensure that the unobtrusive JavaScript is enabled in your web.config (it should be by default).
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />  

Step 2
Now, let's go ahead and implement the "Germany" and "Mexico" action methods that will return a PartialView.
    NorthwindEntities db = new NorthwindEntities();  
    public PartialViewResult Germany()  
    {  
        var result = from r in db.Customers  
                        where r.Country == "Germany"  
                        select r;  
        return PartialView("_Country", result);  
    }  
    public PartialViewResult Mexico()  
    {  
        var result = from r in db.Customers  
                        where r.Country == "Mexico"  
                        select r;  
        return PartialView("_Country", result);  
    }  


So, in both of the PartialViewResult methods I have used a LINQ query that will filter records on country and then pass the results to a partial view page "_Country.cshtml". I have placed this file in the "Shared" folder so that any view can access it. Let's move on to see the partial view page "_Country.cshtml".
 
Step 3
I made this view page strongly typed by using @model and then iterated through the model data to create a nice tabular format.
    @model IEnumerable<MvcActionLink.Models.Customer>  
    <table>  
        <tr>  
            <th>  
                @Html.DisplayNameFor(model => model.ContactName)  
            </th>  
            <th>  
                @Html.DisplayNameFor(model => model.Address)  
            </th>  
        </tr>  
    @foreach (var item in Model) {  
        <tr>  
            <td>  
                @Html.DisplayFor(modelItem => item.ContactName)  
            </td>  
            <td>  
                @Html.DisplayFor(modelItem => item.Address)  
            </td>  
        </tr>  
    }  
    </table>  


Now, you all set to run the application.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Display A Document From SQL Server To A Web Page In ASP.NET MVC

clock October 27, 2020 10:19 by author Peter

In this blog post, I'll discuss a useful yet easy to implement document viewer API. Using that you can display a source file (e.g. Word, Presentation, Diagram, PSD) from your server to your browser without downloading it.
 

Some Use-Cases
    Display a Word resume to a user in a web browser
    Render a Visio Diagram on the web page
    View a Presentation or a Slide online without downloading it

Implementation
 
Now as the use-cases are clear, we will dive into the API implementation. It'll be an ASP.NET MVC application. We'll pull data/documents from the database and save it to a stream. You have to specify the file format in order to render it correctly. The source document will be then rendered to HTML. Eventually, our controller will return this stream to the View/browser.  
    public ActionResult Index()  
    {  
         License lic = new License();  
         lic.SetLicense(@"D:/GD Licenses/Conholdate.Total.NET.lic");  
         MemoryStream outputStream = new MemoryStream();  
         //specify just the file name if you are pulling the data from database   
         string fileName = "sample.pdf";  
      
         FileType fileType = FileType.FromExtension(Path.GetExtension(fileName));  
      
         using (Viewer viewer = new Viewer(() => GetSourceFileStream(fileName), () => new LoadOptions(fileType)))  
         {  
               HtmlViewOptions Options = HtmlViewOptions.ForEmbeddedResources(  
                    (pageNumber) => outputStream,  
                    (pageNumber, pageStream) => { });  
               viewer.View(Options);  
         }
         outputStream.Position = 0;  
         return File(outputStream, "text/html");  
                   
    }  
    private Stream GetSourceFileStream(string fileName) =>  
                new MemoryStream(GetSourceFileBytesFromDb(fileName));  
      
    //TODO: If you want to pull the data from the DB  
    private byte[] GetSourceFileBytesFromDb(string fileName) =>  
                System.IO.File.ReadAllBytes(fileName);  


Have a look at this image/screenshot. We displayed a PDF from Server to Browser.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: ViewBag, ViewData And TempData In MVC

clock October 23, 2020 09:44 by author Peter

ViewBag, ViewData, and TempData all are objects in ASP.NET MVC and these are used to pass the data in various scenarios.

The following are the scenarios where we can use these objects.
    Pass the data from Controller to View.
    Pass the data from one action to another action in the same Controller.
    Pass the data in between Controllers.
    Pass the data between consecutive requests.

ViewBag
ViewBag is a dynamic object to pass the data from Controller to View. And, this will pass the data as a property of object ViewBag. And we have no need to typecast to read the data or for null checking. The scope of ViewBag is permitted to the current request and the value of ViewBag will become null while redirecting.
 
Ex Controller
    Public ActionResult Index()  
    {  
        ViewBag.Title = “Welcome”;  
        return View();  
    }  

View
    <h2>@ViewBag.Title</h2>  

ViewData
ViewData is a dictionary object to pass the data from Controller to View where data is passed in the form of key-value pair. And typecasting is required to read the data in View if the data is complex and we need to ensure null check to avoid null exceptions. The scope of ViewData is similar to ViewBag and it is restricted to the current request and the value of ViewData will become null while redirecting.
 
Ex
Controller:

    Public ActionResult Index()  
    {  
        ViewData[”Title”] = “Welcome”;  
        return View();  
    }  


View
    <h2>@ViewData[“Title”]</h2>  

TempData
TempData is a dictionary object to pass the data from one action to other action in the same Controller or different Controllers. Usually, TempData object will be stored in a session object. Tempdata is also required to typecast and for null checking before reading data from it. TempData scope is limited to the next request and if we want Tempdata to be available even further, we should use Keep and peek.
 
Ex - Controller
    Public ActionResult Index()  
    {  
        TempData[”Data”] = “I am from Index action”;  
        return View();  
    }  

    Public string Get()  
    {  
        return TempData[”Data”] ;  
    }  

To summarize, ViewBag and ViewData are used to pass the data from Controller action to View and TempData is used to pass the data from action to another action or one Controller to another Controller.
 
Hope you have understood the concept of ViewBag, ViewData, and TempData.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Using Auto-Mapper In An ASP.NET Core MVC Application

clock August 25, 2020 08:24 by author Peter

In today’s article we will look at an extremely useful feature. In many applications, the data we collect on the user interface needs to be converted to some different form before it can be stored in the data store and vice versa. This requires some mapping logic and it is mostly done using mapping classes and logic. Today, we will look at a ready to use Nuget package to do this mapping for us and make the process amazingly simple. We will apply this mapping in an ASP.NET Core MVC application.

Creating the .NET Core MVC application
We will start by creating an ASP.NET Core 3.1 MVC application using Visual Studio 2019 community edition as below,

We select the ASP.NET Core web application and click “Next”

Next, we enter the project details and click “Create”

From the list of ASP.NET Core web applications, we select “Web Application (Model-View-Controller) and leave all other values as default.
 
We now have the ASP.NET Core MVC application created. The next step is to add the “AutoMapper” Nugget package as below,

Remember to select the latest version.

After that create three classes under the “Models” folder as below,
 
Employee.cs

    namespace WebAppAutoMapper.Models { 
        publicclassEmployee { 
            publicstring FirstName { 
                get; 
                set; 
            } 
            publicstring LastName { 
                get; 
                set; 
            } 
            publicstring StreetAddress { 
                get; 
                set; 
            } 
            publicstring City { 
                get; 
                set; 
            } 
            publicstring Province { 
                get; 
                set; 
            } 
            publicstring Country { 
                get; 
                set; 
            } 
            publicstring Email { 
                get; 
                set; 
            } 
            publicstring Phone { 
                get; 
                set; 
            } 
            publicEmployee() { 
                FirstName = "Munib"; 
                LastName = "Butt"; 
                StreetAddress = "123 Street One"; 
                City = "Toronto"; 
                Province = "Ontario"; 
                Country = "Canada"; 
                Email = "[email protected]"; 
                Phone = "+14161112222"; 
            } 
        } 
    } 

EmployeeDTO.cs

    namespace WebAppAutoMapper.Models { 
        publicclassEmployeeDTO { 
            publicstring Name { 
                get; 
                set; 
            } 
            publicstring Address { 
                get; 
                set; 
            } 
            publicstring Email { 
                get; 
                set; 
            } 
            publicstring Phone { 
                get; 
                set; 
            } 
        } 
    } 

And finally,AutoMap.cs

    using AutoMapper; 
     
    namespace WebAppAutoMapper.Models 
    { 
    publicclassAutoMap : Profile 
        { 
    publicAutoMap() 
            { 
                CreateMap<Employee, EmployeeDTO>() // means you want to map from Employee to EmployeeDTO 
                .ForMember(d => d.Name, source => source.MapFrom(s => s.FirstName + " " + s.LastName)) 
                .ForMember(d => d.Address, source => source.MapFrom(s => s.StreetAddress + ", " + s.City + ", " + s.Province + ", " + s.Country)) 
                .ForMember(d => d.Phone, source => source.MapFrom(s => s.Phone)) 
                .ForMember(d => d.Email, source => source.MapFrom(s => s.Email)); 
            } 
        } 
    } 

Here we see that we have an Employee class which has several properties. We also have an EmployeeDTO class which has fewer properties than the Employee class. Now, we want to map the values from the Employee class to the EmployeeDTO class using some mapping logic. This logic is implemented in the AutoMap.cs class which inherits from the Profile class.
 
Finally, we setup the AutoMap in the Startup.cs class in the “ConfigureServices” function as below,

    using Microsoft.AspNetCore.Builder; 
    using Microsoft.AspNetCore.Hosting; 
    using Microsoft.Extensions.Configuration; 
    using Microsoft.Extensions.DependencyInjection; 
    using Microsoft.Extensions.Hosting; 
    using AutoMapper; 
    using WebAppAutoMapper.Models; 
     
    namespace WebAppAutoMapper 
    { 
    publicclassStartup 
        { 
    publicStartup(IConfiguration configuration) 
            { 
                Configuration = configuration; 
            } 
     
    public IConfiguration Configuration { get; } 
     
    // This method gets called by the runtime. Use this method to add services to the container. 
    publicvoid ConfigureServices(IServiceCollection services) 
            { 
                services.AddAutoMapper(c => c.AddProfile<AutoMap>(), typeof(Startup)); 
                services.AddControllersWithViews(); 
            } 
     
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 
    publicvoid Configure(IApplicationBuilder app, IWebHostEnvironment env) 
            { 
    if (env.IsDevelopment()) 
                { 
                    app.UseDeveloperExceptionPage(); 
                } 
    else 
                { 
                    app.UseExceptionHandler("/Home/Error"); 
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 
                    app.UseHsts(); 
                } 
                app.UseHttpsRedirection(); 
                app.UseStaticFiles(); 
     
                app.UseRouting(); 
     
                app.UseAuthorization(); 
     
                app.UseEndpoints(endpoints => 
                { 
                    endpoints.MapControllerRoute( 
                        name: "default", 
                        pattern: "{controller=Home}/{action=Index}/{id?}"); 
                }); 
            } 
        } 
    } 

Now, all the plumbing is in place and we can use the mapping as below in the Home Controller,

    using System.Diagnostics; 
    using Microsoft.AspNetCore.Mvc; 
    using Microsoft.Extensions.Logging; 
    using WebAppAutoMapper.Models; 
    using AutoMapper; 
     
    namespace WebAppAutoMapper.Controllers 
    { 
    publicclassHomeController : Controller 
        { 
    privatereadonly ILogger<HomeController> _logger; 
    privatereadonly IMapper _mapper; 
     
    publicHomeController(ILogger<HomeController> logger, IMapper mapper) 
            { 
                _logger = logger; 
                _mapper = mapper; 
            } 
     
    public IActionResult Index() 
            { 
                Employee emp = new Employee(); 
    var empDTO = _mapper.Map<EmployeeDTO>(emp); 
    return View(); 
            } 
     
    public IActionResult Privacy() 
            { 
    return View(); 
            } 
     
            [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 
    public IActionResult Error() 
            { 
    return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 
            } 
        } 
    } 

We can put a breakpoint at the “return View();” line in the Index function and see the Employee DTO values as below,

Here we see that the empDTO object has the values extracted and mapped from the Employee object.

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 Handle Multiple Submit Buttons in ASP.NET MVC 6?

clock July 30, 2020 13:16 by author Peter

Today, let me explain you how to handle multiple submit buttons in ASP.NET MVC 6. Sometimes you will need to handle multiple submit buttons on a similar form as as in the following picture.

As you can see on the above picture, we've got the three buttons Login, Register and Cancel. Here every button has totally different functionality. in this way every submit button will post a form to the server but will provide totally different values of every button.

Make a controller with one action method that accepts other parameters, one is for the model and the other is for determining the status of the button click.
[HttpPost] 
public ActionResult Index(Login model, string command) 

if (command=="Login") 

// do stuff 
return RedirectToAction("Home"); 

else if (command=="Register") 

// do stuff 
ViewBag.msg = "You have Clicked Register button"; 
return View(); 


else if (command=="Cancel") 

// do stuff 
ViewBag.msg = "You have Clicked Cancel Button"; 
return View(); 

else 

return View(); 



In the preceding code snippet, assume you clicked on the Login button, then the command parameter can have the values Login, null, null respectively. Create a View for the preceding controller.
@model MvcMultipleSubmitButtons.Models.Login 
@{ 
ViewBag.Title = "Index"; 

<h2> 
Handling multiple submit buttons in MVC </h2> 
<h5 style="color: Red">@ViewBag.msg</h5> 
<form action="Home/Index" id="myform" method="post" >  
//here action name is Index, controller name is Home. So the action path is Home/Index 
<table> 
<tr> 
<td> 
UserName 
</td> 
<td> 

</td> 
<td>@Html.TextBoxFor(m => m.userName) 
</td> 
<td> 
@Html.ValidationMessageFor(m => m.userName) 
</td> 
</tr> 
<tr> 
<td> 
Password 
</td> 
<td> 

</td> 
<td>@Html.TextBoxFor(m => m.password) 
</td> 
<td> 
@Html.ValidationMessageFor(m => m.password) 
</td> 
</tr> 
</table> 
<br/> 

<div style="padding-left: 80px;"> 
<input type="submit" id="Login" value="Login" name="Command" title="Login" /> 
<input type="submit" id="Register" value="Register" name="Command" title="Register" /> 
<input type="submit" value="Cancel" name="Command" title="Cancel" /> 

</div> 
</form> 


You can declare the form tag in another way as within the following:
@using(Html.BeginForm("Index","Home",FormMethod.Post)) 
{  
//here action name is Index, controller name is Home and form method is post. 
}


Note: there's a relation between button name and action method parameter. for instance, the button name is “Command”, the action parameter name ought to be “command”.

You can have different names for each button. So in that case you need to handle it as in the following:
<input type="submit" id="Login" value="Login" name="Command1" title="Login" /> 
<input type="submit" id="Register" value="Register" name="Command2" title="Register" /> 
<input type="submit" value="Cancel" name="Command3" title="Cancel" /> 


Controller
public ActionResult Index(Login model, string command1, string command2, string command3) 

   // here command1 is for Login, command2 is for Register and command3 is for cancel 


Create a Model class with the name Login.
public class Login 

    public string userName { get; set; } 
    public string password { get; set; } 

I hope it helps for you!

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 UK - HostForLIFE.eu :: How to Delete Multiple Items in ASP.NET with JSON?

clock June 26, 2020 13:15 by author Peter

Today, I want to show you how to delete multiple Items in ASP.NET with JSON. JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language. Now, open your project and write the following code:

View
<table class="table"> 
@foreach (var role in Model) { 
<tr> 
    <td> 
        <input id="responsable1" name="checkResp" value="@role.id" type="checkbox" /> 
        <strong>@role.Name</strong> 
    </td> 
</tr> 

</table> 
<input id="DeleteBtn" type="button" value="Delete Selected" /> 
<script> 
$("#DeleteBtn").on("click", function() { 
    var boxData = []; 
    $("input[name='checkResp']:checked").each(function() { 
        boxData.push($(this).val()); 
    }); 
    $.ajax({ 
        url: '/Roles/DeleteMultiple', 
        data: { 
            RoleId: boxData.join(",") 
        }, 
        cache: false, 
        type: "POST", 
        timeout: 10000, 
        dataType: "json", 
        success: function(result) { 
            window.location.reload(); 
        } 
    }); 
}); 
</script> 


Controller
[HttpPost] 
public JsonResult DeleteMultiple(string RoleId) { 
ApplicationDbContext db = new ApplicationDbContext(); 
var RoleIds = RoleId.Split(','); 
foreach(var id in RoleIds) { 
    int idConverted = Convert.ToInt32(id); 
    Roles roleid = db.Roles.Find(idConverted); 
    db.Roles.Remove(roleid); 

context.SaveChanges(); 
var message = "Selected roles have been deleted"; 
return Json(message); 


DeleteMultiple - Action Name
Roles - Controller Name

 

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 :: HTML Helpers In ASP.NET MVC

clock April 9, 2020 05:10 by author Peter

What is an Html Helper?
Html helper is a method that is used to render HTML content in a view. Html helpers are implemented using an extension method. If you want to create an input text box with

id=email and name in email:
  <input type=text id=email name=email value=’’/> 


This is all the Html we need to write -- by using the helper method it becomes so easy:
  @Html.TextBox(‘email’) 

It will generate a textbox control whose name is the email.

If we want to assign the value of the textbox with some initial value then use the below method:
  @Html.TextBox(‘email’,’[email protected]’) 

If I want to set an initial style for textbox we can achieve this by using the below way:
  @Html.TextBox(‘email’,’[email protected]’,new {style=’your style here’ , title=’your title here’});  

Here the style we pass is an anonymous type.

If we have a reserved keyword like class readonly and we want to use this as an attribute  we will do this using the below method, which means append with @ symbol with the reserved word.
  @Html.TextBox(‘email’,’[email protected]’,new {@class=’class name’, @readonly=true}); 

If we want to generate label:
  @Html.Label(‘firstname’,’sagar’) 

For password use the below Html helper method to create password box:
  @Html.Password(“password”) 

If I want to generate a textarea then for this also we have a method:
  @Html.TextArea(“comments”,”,4,12,null)  

In the above code 4 is the number of rows and 12 is the number of columns.

To generate a hidden box:
  @Html.Hidden(“EmpID”) 

Hidden textboxes are not displayed on the web page but used for storing data and when we need to pass data to action method then we can use that.

Is it possible to create our Html helpers in asp.net MVC?

Yes, we can create our Html helpers in MVC.

Is it mandatory to use Html helpers?

No, we can use plain Html for that but Html helpers reduce a significant amount of Html code to write that view.
Also, your code is simple and maintainable and if you require some complicated logic to generate view then this is also possible.



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