Windows 2012 Hosting - MVC 4 and SQL 2012 BLOG

Tutorial and Articles about Windows Hosting, SQL Hosting, MVC Hosting, and Silverlight Hosting

ASP.NET MVC Hosting - ASPHostPortal :: Session State Performance Issue in ASP.NET MVC

clock January 15, 2016 20:54 by author Jervis

I cannot recall any real Web Application that doesn’t make use of the Session State feature, the one that is capable to store data that are available across multiple requests from the same browser. More over, in this very modern times, Web Applications tends to make extensive use of Ajax requests to the server, in order to avoid page refreshes. So the question here is, have you ever noticed performance issues while making multiple ajax requests to an ASP.NET MVC action when using Session data?

Put Session into the Context

Before demonstrating the real problem with coding, let’s find out the basics on how Session works. When a new request is arrived to the server for the first time, which means no session cookie is contained, the server will create a new session identifier accessible through the

System.Web.HttpContext.Current.Session.SessionID

Though, this does not mean that from now on all requests back to server will contain a session cookie. Instead, this will happened only if a specific request store some data in the Session. In other words,ASP.NET Framework adds the session cookie to the response at the first time some data is stored in the session. So how is this related to performance issues? Well, normally ASP.NET can process multiple requests from the same browser concurrently which means for example, multiple Ajax requests can be processed simultaneously.

The above schema works only when no session cookie is contained in browser’s request or in other words, server hasn’t yet stored any data into the Session. If server does store some data into the session and hence adds a session cookie in the response, then all subsequent requests using the same session cookie are queued and proccessed sequentially.

This is actually a normal behavior, cause consider for example that multiple requests may modify or read the same Session key value simultaneously. That would certainly result in inconsistent data.

Code time

Create an ASP.NET Empty Web Application checking the MVC option and add the following HomeController.

[OutputCache(NoStore = true, Duration = 0)]
    public class HomeController : Controller
    {
        public List<string> boxes = new List<string>() { "red", "green", "blue", "black", "gray", "yellow", "orange" };
        // GET: Home
        public ActionResult Index()
        {
            return View();
        } 

        public string GetBox()
        {
            System.Threading.Thread.Sleep(10);
            Random rnd = new Random();
            int index = rnd.Next(0, boxes.Count); 

            return boxes[index];
        } 

        public ActionResult StartSession()
        {
            System.Web.HttpContext.Current.Session["Name"] = "Jervis"; 

            return RedirectToAction("Index");
        }
    }

The controller has a GetBox which returns a random color from a list of colors defined in the class. We will use it’s value to add a div element in the view having the background-color property set accoarding the returned value. More over, has a StartSession action which simply stores a session value and hence it’s the point that the server adds a session cookie into the response. You will need to add the Index view so right click in the index method, add it and paste the following code.

<!DOCTYPE html>
<html lang="en" ng-app="asyncApp">
<head>
    <title>Troubleshooting ASP.NET MVC Performance Issues</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script>
    <link href="~/Content/Site.css" rel="stylesheet" />
</head>
<body ng-controller="asyncCtrl" ng-init="getBoxes()">
    <nav role="navigation" class="navbar navbar-default navbar-fixed-top">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" data-target="#navbarCollapse" data-toggle="collapse" class="navbar-toggle">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
            </div>
            <!-- Collection of nav links and other content for toggling -->
            <div id="navbarCollapse" class="collapse navbar-collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Performace testing</a></li>
                    <li>
                        @Html.ActionLink("Start Session", "StartSession")
                    </li>
                    <li>
                        <a class="links" ng-click="getBoxes()">Not resolved</a>
                    </li>
                    <li>
                        <a class="links" ng-click="getBoxes(true)">Resolved</a>
                    </li>
                    <li>
                        <form class="navbar-form">
                            <label class="checkbox" style="margin-top:5px">
                                @Html.CheckBox("isSessionNewChk", Session.IsNewSession, new { @disabled = "disabled" })
                                Is Session New
                            </label>
                        </form>
                    </li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#">{{boxes.length}} Boxes</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <br /><br /><br />
    <div class="container">
        <div class="row">
            <div id="boxesContainer" ng-repeat="color in boxes track by $index">
                <div class="box" ng-class="color" />
            </div>
        </div>
        <br />
        <div class="row">
            <div id="timeOccured" ng-show="showResults" class="alert" ng-class="isResolved()" ng-bind="timeElapsed"></div>
        </div>
    </div>
    <script src="~/Scripts/app.js"></script>
</body>
</html>

Add a Content folder in the root of your application and create the following css stylesheet.

.box {
    height: 15px;
    width: 15px;
    margin: 2px;
    float:left;
} 

#timeOccured {
    clear:both;
} 

.links {
    cursor:pointer;
} 

.red {
    background-color: red;
} 

.green {
    background-color: green;
} 

.blue {
    background-color: blue;
} 

.black {
    background-color: black;
} 

.gray {
    background-color: gray;
} 

.yellow {
    background-color: yellow;
} 

.orange {
    background-color: orange;
}

You will have noticed that I make use of simple AngularJS code but that’s OK if you aren’t familiar with it. Add a Scripts folder and create the following app.js javascript file.

angular.module('asyncApp', [])
    .value('mvcuri', 'http://localhost:49588/home/getbox')
    .value('mvcurisessionresolved', 'http://localhost:49588/SessionResolved/getbox')
    .controller('asyncCtrl', function ($http, $scope, mvcuri, mvcurisessionresolved) { 

        $scope.boxes = [];
        $scope.showResults = false;
        var uri; 

        $scope.getBoxes = function (resolved) {
            var start = new Date();
            var counter = 300; 

            if (resolved)
                uri = mvcurisessionresolved;
            else
                uri = mvcuri; 

            // Init variables
            $scope.boxes = [];
            $scope.showResults = false;
            $scope.timeElapsed = ''; 

            for (var i = 0; i < 300; i++) {
                $http.get(uri)
                    .success(function (data, status, headers, config) {
                        $scope.boxes.push(data);
                        counter--; 

                        if (counter == 0) {
                            var time = new Date().getTime() - start.getTime();
                            $scope.timeElapsed = 'Time elapsed (ms): ' + time;
                            $scope.showResults = true;
                        }
                    })
                        .error(function (error) {
                            $scope.timeElapsed = error.Message;
                        }).finally(function () {
                        });
            }
        }; 

        $scope.isResolved = function () {
            return uri == mvcuri ? 'alert-danger' : 'alert-success';
        } 

    });

Make sure you replace the localhost:port with yours. Before explain all application’s functionality let’s add a new MVC controller named SessionResolvedController.

[OutputCache(NoStore = true, Duration = 0)]
    public class SessionResolvedController : Controller
    {
        public List<string> boxes = new List<string>() { "red", "green", "blue", "black", "gray", "yellow", "orange" }; 

        public string GetBox()
        {
            System.Threading.Thread.Sleep(10);
            Random rnd = new Random();
            int index = rnd.Next(0, boxes.Count); 

            return boxes[index];
        }
    }

At this point you should be able to fire your application.

So what is happening here? When the application starts, 300 Ajax calls are sent to the HomeController’sGetBox action and foreach color returned a respective box is added to the view.

<body ng-controller="asyncCtrl" ng-init="getBoxes()"> 

<div id="boxesContainer" ng-repeat="color in boxes track by $index">
     <div class="box" ng-class="color" />
 </div>

Every time you refresh the Page you will notice that the Is Session New checkbox is checked, which means that there isn’t yet a session cookie sent to the browser. All Ajax requests are processed concurrently as expected and the time elapsed to complete all the ajax calls is displayed in a red box under all boxes. The Start Session button will simply store a session value as follow.

System.Web.HttpContext.Current.Session["Name"] = "Jervis";

Press the button and notice the difference in the elapsed time for displaying all the 300 boxes. Also notice that the checkbox isn’t checked anymore.

Now that there is a Session cookie in each request to the server, all requests are proccessed sequentially as described previously. That’s why we need twice the time we needed before storing a session variable. You can repeat the same ajax requests without refreshing the page by clicking the Not Resolved button.

Solution

At the moment, if you press the Resolved button you will get the same results calling theSessionResolvedController’s GetBox() action.

<a class="links" ng-click="getBoxes(true)">Resolved</a>

Notice that we don’t read or modify any Session state data when calling the GetBox() actions, so the question is, is there anything that we can do to prevent our requests being processed sequentially despite the fact that they contain a cookie session? The answer is YES and it’s hidding in the SessionState attribute that can be applied in the controller’s class as follow:

[SessionState(SessionStateBehavior.Disabled)]
    public class SessionResolvedController : Controller
    {
        public List<string> boxes = new List<string>() { "red", "green", "blue", "black", "gray", "yellow", "orange" }; 

        public string GetBox()
        {
            System.Threading.Thread.Sleep(10);
            Random rnd = new Random();
            int index = rnd.Next(0, boxes.Count); 

            return boxes[index];
        }
    }

Applying this attribute to the controller will make all requests targeting this controller processed concurrently. Build, run your application and repeat what we did before. Notice that the Resolved button now finishes at the half time which was the time needed when no session cookie existed in the request.

I run the application without debugging in order to get better results. If you run with debugging you will get higher delays but that should not be a problem, the differences will be still noticeable.

And following is a complete demonstration of what we have done till now. When I fired the application for the first time, it tooked 928 milliseconds to complete all 300 Ajax requests. Then I clicked to create a Session cookie and that caused an important performance issue increasing the delay to 2201 milliseconds! When I requested the data through the SessionResolvedController the delay was almost the same when there wasn’t any Session cookie.

I have also used the

[OutputCache(NoStore = true, Duration = 0)]

to the MVC Controllers which will result to ask the browser (client) not to store the content retrieved from the server. This way the test is even more reliable.



SQL 2014 Hosting - ASPHostPortal :: Make Your SSAS Works Like a Private Jet!

clock December 10, 2015 19:54 by author Jervis

SQL Server Analysis Services (SSAS) Tabular is a popular choice as an analytical engine for many customers. With its state-of-the-art compression algorithms, multi-threaded query processor and in-memory capabilities, SSAS Tabular can provide super quick access to data by reporting client applications. However, as a consultant, I have been called by many clients to resolve slow query performance when accessing data from SSAS Tabular models. My experiences have taught me most, if not all, of the performance issues can be resolved by taking care of the following five subject areas. 

Estimate Current Size and Growth Carefully

Tabular models compress data really well and on an average, you can expect to see 10x the compression rates (though it can be much more or less depending on the cardinality of your data). However, when you are estimating the size of your model as well as future growth, a rough figure like this is not going to be optimal. If you already have data sitting in a data warehouse, import a subset of that data — say a month — to find the model size for that and then extrapolate the value based on the required number of rows / years as well as the number of columns. If not, try to at least get a subset of the data from the source to find the model size. There are tools like BISM Memory Report and Vertipaq Analyzer that can further help in this process.

It is also important to record the number of users who will be accessing the system currently as well as the estimated growth for the number of users.

Select or Upgrade Hardware Appropriately

Everyone knows SSAS Tabular is a memory intensive application, and one major issue I have seen is only the RAM is considered when hardware selections are made. However, just focusing on the RAM is not enough and there are a lot of other variables. Suppose all the other variables are constant and there is an unlimited budget, these are the recommendations:

CPU Speed – The faster, the better, will help in computing results faster especially when there is a bottleneck on the single-threaded formula engine.

CPU Cores – In theory, the more the better as it helps in managing concurrent user loads. However, in reality, a rise in the number of cores usually corresponds to a decrease in the CPU speed due to management overload. So a balanced approach has to be taken when determining the CPU Cores and Speed. Also, licensing cost increases with the number of cores for many software.

CPU Sockets – The lesser, the better as SSAS Tabular is not NUMA aware till SQL 2014. However, this is expected to change in SQL 2016 where some NUMA optimization has been made. For large tabular models, it might be a challenge to go single socket as the amount of RAM that can be supported on a system will depend on the CPU sockets.

CPU Cache – The more, the better. Retrieving data from CPU caches are 10-100x faster than retrieving data from RAM.

CPU Architecture – The newer, the better due to the hardware performance optimizations. For eg, Intel Xeon processors with Haswell architecture is always going to be faster than Sandy architecture keeping all other variables constant.

Amount of RAM – Should have at least 2.5x the model size, if the model is going to be processed on the same server. The amount of RAM can be lesser in cases of certain scale out architectures where the model is processed in a separate server.

RAM Speed – The faster, the better (yes, RAMs have speed too!) This is very important for a memory-bound application like Tabular and should always go for the faster speeds, if budget allows.

Storage – Not important at all as it does not have any effect on query performance. However, if budget allows, it might not be a bad idea to get faster storage like SSDs, as that will help in maintenance related activities like backup, storage or even getting the tabular model online faster when the service is restarted. Apart from this, there are other factors also like network latency, server architecture (scale out), etc that have to be considered, but depending on the budget and specific customer requirements, a balanced approach will have to be made.

Design the Data Model Properly

Tabular is really good at performance and in the case of small models, is extremely forgiving in terms of bad design. However, when the amount of data grows, performance problems begin to show up. In theory, you will get the best performance in SSAS tabular if the entire data is flattened into a single table. However, in reality, this would translate to an extremely bad user experience as well as a lengthy and expensive ETL process. So the best practice is to have a star schema, generally. Also, it is recommended to only include the relevant columns from the source tables, as increasing the columns will result in an increase in model size which in turn will result in slower query performances. Increase in number of rows might still be ok as long as the cardinality of the columns don’t change much.

Depending on the specific customer requirements, there could be deviations from the best practices. For e.g., we built custom aggregate tables along with the detailed fact table in the case of a very large production model for a client. The resultant measure had a conditional statement to retrieve data from the aggregate table if the detailed level dimension data was not used in the report. Since the aggregate table was only 1/10 the size of the detailed fact table, the query came out 10x times faster whenever the details were not used, which was almost 90% of the times.

Optimize the DAX Calculations

In case of small models, Tabular is extremely forgiving in terms of bad DAX code also. However, just like in the case of bad design, performance takes a hit for the worse as you increase the data, add more users, or run complex queries. DAX performance tuning is the most difficult to tune from the current list, and it is important to have a strategy for maintaining and tuning the performance. A good place to start would be the Performance Tuning of Tabular models in SSAS 2012 whitepaper.

Monitor User Query Patterns and Train Users

Once your model is in production, it is important to keep monitoring the user query patterns as well as the resources to see potential bottlenecks. Through this, you can find whether the performance issues are being caused due to inefficient DAX, bad design, insufficient resources or most importantly, whether it is just because a user is using the model inefficiently. For e.g., in one of the cases, we found out the slow performance for all users was due to a single user dumping the entire 100 GB model into spreadsheets so he could perform custom calculations on top of it. This blocked the queries for all the other users and made things really slow for them. With appropriate requirement gatherings, we ensured all the required calculations for that user were there in the model and then trained the user to use the model for his analytics.

The success of any tabular project depends on the adoption by the end users and it is needless to say the adoption would be much better if the system is fast. These 5 tips will ensure you already have a jumpstart on that journey.

Looking to Use SQL Server Analysis Services Hosting?

As this is intermediate service, you can get this SQL Server Analysis Services on our Windows Dedicated server plan. You can start from our Bundled Cloud Platinum Class to get this service running on your server. This plan has included

- Windows Server 2008/2012 license
- 2 x 2.0 Ghz Core
- 4 GB RAM --> FREE Upgrade to 8 GB RAM (Use Promo Code ‘DOUBLERAM’)
- 2 x 500 GB Storage
- 20000 GB Bandwith
- 1000 Mbps Connection speed
- 4 Static IP
- Full 24 x 7 RDP Access
- Full 24/7 Firewall Protection
- Standard ver. SQL 2008/2012
- Support MySQL db
- PLESK Control Panel
- Antivirus
- Unlimited of MSSQL dbs
- Unlimited of MySQL dbs
- FREE SmarterMail service if you register this December

Get a HUGE discount for this Christmas!! For more information, please visit our official site at http://www.asphostportal.com.



ASP.NET MVC 6 Hosting - ASPHostPortal :: Introduction Tag Helpers MVC 6

clock December 3, 2015 21:31 by author Jervis

MVC6 introduces a new feature called Tag Helpers. In this post, we will explore how tag helpers can be used to improve the readability of your Razor views that generate HTML forms.

How do Tag Helpers work?

Tag Helpers are an alternative to HTML helpers for generating HTML. The easiest way to show this is with an example.

Let’s start by looking at an extremely simple example of a login view that is bound to a LoginViewModel that contains a UserName and a Password:

public class LoginViewModel
{
    public string UserName { get; set; }
    public string Password { get; set; }
}

Here is how we would generate an HTML input for the UserName property using an HTML Helper and a Tag Helper.

<!--Create an input for UserName using Html Helper-->
@Html.EditorFor(l => l.UserName)
<!--Create an input for UserName using Tag Helper-->
<input asp-for="UserName" />

With the HTML helper, we call C# code that return some HTML. With Tag Helpers we augment some HTML with special tag helper attributes. These special attributes are processed by MVC which will generate some HTML. Both of these approaches above will generate an input that looks like this:

<input name="UserName" class="text-box single-line" id="UserName" type="text" value="">

Why is this better?

At first glance, it might look like Tag Helpers are just a syntax change with no obvious benefits. The difference however, can make your Razor forms much more readable. Let’s say we wanted to do something simple like add a class to our UserName input:

<!--Create an input with additional class for UserName using Html Helper-->
@Html.EditorFor(l => l.UserName, new { htmlAttributes = new { @class = "form-control" } })
<!--Create an input with additional class for UserName using Tag Helper-->
<input asp-for="UserName" class="form-control" />

As you can see, the HTML helper approach becomes very hard to understand while the tag helper approach is very clear and concise.

Here is a full blown example of a login form using HTML helpers:

@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, 
FormMethod.Post, new { role = "form" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
 
    <div class="form-group">
        <div class="row">
            @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>
    <div class="form-group">
        <div class="row">
            @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
                @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>
 
    <div class="form-group">
        <div class="row">
            <div class="col-md-offset-2 col-md-2">
                <input type="submit" value="Log in" class="btn btn-primary" />
            </div>
        </div>
    </div>
}

And now the same form using tag helpers:

<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewBag.ReturnUrl" 
method="post" class="form-horizontal" role="form">
    <div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="UserName" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="UserName" class="form-control" />
            <span asp-validation-for="UserName" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <label asp-for="Password" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="Password" class="form-control" />
            <span asp-validation-for="Password" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Log in" class="btn btn-default" />
        </div>
    </div>
</form>

Overall, the tag helper version is much more readable. I especially like that we no longer need to use a using statement to generate a form element. That had always felt like a bit of a hack to me.

Another nice thing with the form tag helpers is that we don’t need to remember to explicitly add the AntiForgeryToken. The form tag helper does this automatically unless we explicitly turn it off using asp-anti-forgery=”false”

Of course, Visual Studio does a good job of highlighting the tag helper attributes so it is easy to distinguish them from regular HTML attributes

We also get full Intellisense inside the asp-for attributes.

How to enable Tag Helpers

The MVC Tag Helpers are located in the Microsoft.AspNet.Mvc.TagHelpers package so you will need to add a reference to that in your project.json file. Once you have added the reference, you can enable tag helpers in all your views by adding the following code to_GlobalImports.cshtml.

@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"



ASP.NET MVC Hosting - ASPHostPortal :: The Difference Between Controller and View in ASP.NET MVC

clock November 12, 2015 20:28 by author Jervis

One of the basic rules of MVC is that views should be only – exactly – views, that is to say: objects that present to the user something that is already “worked and calculated”.

They should perform little, if not none at all, calculation. All the significant code should be in the controllers. This allows better testability and maintainability.

Is this, in Microsoft’s interpretation of MVC, also justified by performance?

We tested this with a very simple code that does this:

– creates 200000 “cat” objects and adds them to a List

– creates 200000 “owner” objects and adds them to a List

– creates 200000 “catowner” objects (the MTM relation among cats and owners) and adds them to a List

– navigates through each cat, finds his/her owner, removes the owner from the list of owners (we don’t know if cats really wanted this, but their freedom on code fits our purposes).

We’ve run this code in a controller and in a razor view.

The result seem to suggest that the code in views runs just as fast as in controllers even if don’t pre-compile views (the compilation time in our test is negligible).

The average result for the code with the logic in the controller is 18.261 seconds.

The average result for the code with the logic in the view is 18.621 seconds.

The performance seems therefore very similar.

Here is how we got to this result.

Case 1: Calculations are in the CONTROLLER

Models:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebPageTest.Models
{
public class Owner
{
public string Name { get; set; }
public DateTime DOB { get; set; }
public virtual CatOwner CatOwner { get; set; }
}
public class Cat
{
public string Name { get; set; }
public DateTime DOB { get; set; }
public virtual CatOwner CatOwner { get; set; }
}
public class CatOwner
{
public virtual Cat Cat { get; set; }
public virtual Owner Owner { get; set; }
}
}

Controller:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebPageTest.Models;

namespace WebPageTest.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
Stopwatch howLongWillItTake = new Stopwatch();
howLongWillItTake.Start();
List<Owner> allOwners = new List<Owner>();
List<Cat> allCats = new List<Cat>();
List<CatOwner> allCatOwners = new List<CatOwner>();
// create lists with 200000 cats, 200000 owners, 200000 relations
for (int i = 0; i < 200000; i++)
{
//Cat
Cat CatX = new Cat();
CatX.Name = “Cat ” + i.ToString();
CatX.DOB = DateTime.Now.AddDays(i / 10);
//Owner
Owner OwnerX = new Owner();
OwnerX.Name = “Owner ” + i.ToString();
OwnerX.DOB = DateTime.Now.AddDays(-i / 10);
//Relationship “table”
CatOwner CatOwnerXX = new CatOwner();
CatOwnerXX.Cat = CatX;
// Relations
CatOwnerXX.Owner = OwnerX;
CatX.CatOwner = CatOwnerXX;
OwnerX.CatOwner = CatOwnerXX;
//add to list
allCats.Add(CatX);
allOwners.Add(OwnerX);
allCatOwners.Add(CatOwnerXX);
}
// now I remove all the items
foreach (Cat CatToDelete in allCats)
{
Owner OwnerToRemove = CatToDelete.CatOwner.Owner;
allOwners.Remove(OwnerToRemove);
}
// now all cats are free
int numberOfCats = allCats.Count();
int numberOfOwners = allOwners.Count();
howLongWillItTake.Stop();
long elapsedTime = howLongWillItTake.ElapsedMilliseconds;
// give info to the view
ViewBag.numberOfCats = numberOfCats;
ViewBag.numberOfOwners = numberOfOwners;
ViewBag.elapsedTime = elapsedTime;
return View();
}
}
}

View:

<div class=”row”>
<div class=”col-md-12″>
<hr />
<b>Results</b>
<br/>
Cats: @ViewBag.numberOfCats
<br/>
Owners: @ViewBag.numberOfOwners
<br/>
ElapsedTime in milliseconds: @ViewBag.ElapsedTime
<hr />
</div>
</div>

Case 2: Calculations are in the VIEW (pre-compiled)

Models: same as above

Controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebPageTest.Controllers
{
public class HomeBisController : Controller
{
public ActionResult Index()
{
return View();
}
}
}

View:

@using System;
@using System.Collections.Generic;
@using System.Diagnostics;
@using System.Linq;
@using System.Web;
@using WebPageTest.Models;
@using System.Web.Mvc;
@{
Stopwatch howLongWillItTake = new Stopwatch();
howLongWillItTake.Start();
List<Owner> allOwners = new List<Owner>();
List<Cat> allCats = new List<Cat>();
List<CatOwner> allCatOwners = new List<CatOwner>();
//create lists with 200000 cats, 200000 owners, 200000 relations
for (int i = 0; i < 200000; i++)
{
//Cat
Cat CatX = new Cat();
CatX.Name = “Cat ” + i.ToString();
CatX.DOB = DateTime.Now.AddDays(i / 10);
//Owner
Owner OwnerX = new Owner();
OwnerX.Name = “Owner ” + i.ToString();
OwnerX.DOB = DateTime.Now.AddDays(-i / 10);
//Relationship “table”
CatOwner CatOwnerXX = new CatOwner();
CatOwnerXX.Cat = CatX;
// Relations
CatOwnerXX.Owner = OwnerX;
CatX.CatOwner = CatOwnerXX;
OwnerX.CatOwner = CatOwnerXX;
//add to list
allCats.Add(CatX);
allOwners.Add(OwnerX);
allCatOwners.Add(CatOwnerXX);
}
// now I remove all the items
foreach (Cat CatToDelete in allCats)
{
Owner OwnerToRemove = CatToDelete.CatOwner.Owner;
allOwners.Remove(OwnerToRemove);
}
// now all cats are free
int numberOfCats = allCats.Count();
int numberOfOwners = allOwners.Count();
howLongWillItTake.Stop();
long elapsedTime = howLongWillItTake.ElapsedMilliseconds;
// give info to the view

}
<div class=”row”>
<div class=”col-md-12″>
<hr />
<b>Results</b>
<br />
Cats: @numberOfCats
<br />
Owners: @numberOfOwners
<br />
ElapsedTime in milliseconds: @elapsedTime
<hr />
</div>
</div>

 



ASP.NET Hosting - ASPHostPortal.com :: How to Prevent ASP.NET Website From Multiple Database Request

clock October 26, 2015 20:44 by author Dan

It is not good to execute multiple db request for loading single page.  Review your database code to see if you have request paths that go to the database more than once. Each of those round-trips decreases the number of requests per second your application can serve. By returning multiple resultsets in a single database request, you can cut the total time spent communicating with the database.

In order to improve performance you should execute single stored proc and bring multiple resultset in to single db request.  In this article i will explain you how to avoid multiple database request and how to bring multiple resultset into single db request.

Consider a scenario of loading a Product Page, which displays

  • Product Information and
  • Product Review Information

In order to bring 2 database request in single db request, your sql server stored proc should be declared as below.

SQL Server Stored Proc

CREATE PROCEDURE GetProductDetails
 @ProductId bigint,
AS
SET NOCOUNT ON

--Product Information
Select ProductId,
 ProductName,
 ProductImage,
 Description,
 Price
From Product
Where ProductId = @ProductId

--Product Review Information
Select  ReviewerName,
 ReviewDesc,
 ReviewDate
From ProductReview
Where ProductId = @ProductId

Asp.net, C# Code to bring multiple db request into single db request

Code Inside Data Access Class Library (DAL)

public DataSet GetProductDetails()
{
SqlCommand cmdToExecute = new SqlCommand();
cmdToExecute.CommandText = "GetProductDetails";
cmdToExecute.CommandType = CommandType.StoredProcedure;
DataSet dsResultSet = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter(cmdToExecute);

try
{
    var conString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnStr"];
    string strConnString = conString.ConnectionString;
    SqlConnection conn = new SqlConnection(strConnString);

    cmdToExecute.Connection = conn;

    cmdToExecute.Parameters.Add(new SqlParameter("@ ProductId", SqlDbType.BigInt, 8, ParameterDirection.Input, false, 19, 0, "", DataRowVersion.Proposed, _productId));

    //Open Connection
    conn.Open();

    // Assign proper name to multiple table
    adapter.TableMappings.Add("Table", "ProductInfo");
    adapter.TableMappings.Add("Table1", "ProductReviewInfo");
    adapter.Fill(dsResultSet);

    return dsResultSet;             
}
catch (Exception ex)
{
    // some error occured.
    throw new Exception("DB Request error.", ex);
}
finally
{
    conn.Close();
    cmdToExecute.Dispose();
    adapter.Dispose();
}
}

Code Inside Asp.net .aspx.cs page

protected void Page_Load(object sender, EventArgs e)
{
   if (Request.QueryString[ProductId] != null)
   {
      long ProductId = Convert.ToInt64(Request.QueryString[ProductId].ToString()); 
  
      DataSet dsData = new DataSet();

      //Assuming you have Product class in DAL
      ProductInfo objProduct = new ProductInfo();
      objProduct.ProductId = ProductId;
      dsData = objProduct.GetProductDetails();

      DataTable dtProductInfo = dsData.Tables["ProductInfo"];
      DataTable dtProductReviews = dsData.Tables["ProductReviewInfo"];

      //Now you have data table containing information
      //Make necessary assignment to controls
      .....
      .....
      .....
      .....
      ..... 

    }
}


Finish, Happy coding.

Best Windows Shared Hosting Recommendation

ASPHostPortal.com provides our customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Our Shared Hosting. We offers Windows hosting starts from $5/month only. We also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable Windows Shared Hosting, we should be your best choice.



ASP.NET Hosting - ASPHostPortal.com : Paging with ASP.NET Web API OData

clock October 20, 2015 08:58 by author Kenny

Paging with ASP.NET Web API OData

What is OData?

OData, short for Open Data Protocol, defines a protocol for the querying and updating of data utilizing existing Web protocols. OData is a REST-based protocol for querying and updating data and is built on standardized technologies such as HTTP, Atom/XML, and JSON. It is different from other REST-based web services in that it provides a uniform way to describe both the data and the data model. It is considered to be a flexible technology for enabling interoperability between disparate data sources, applications, services and clients.

Step by Step

When the API call returns the list of repositories in the body of the response as a JSON array:

[
  {
    "id": 1234,
    "name": "domain.com",
    "full_name": "user/domain.com",
    ...
  },
  {
    "id": 1111,
    "name": "test",
    "full_name": "user/test",
    ...
  }
]

It does not state the total number of records anywhere in the resulting JSON, not does it return the current page or the number of records per page which you requested. What it does however is to return the pagination information in the Link header of the request. So in the case of my API call above it returns the following Link header:

Link: <https://api.github.com/user/repos?page=5&per_page=2>; rel="next",
      <https://api.github.com/user/repos?page=8&per_page=2>; rel="last",
      <https://api.github.com/user/repos?page=1&per_page=2>; rel="first",
      <https://api.github.com/user/repos?page=3&per_page=2>; rel="prev"

So it allows you to request subsequent pages by requesting the URL in the Link header with the relation type (rel parameter value) of “next”. Also to get the total number of pages you will need to extract the page query parameter from the link with the relation type of last.

Best Windows Shared Hosting Recommendation

ASPHostPortal.com provides our customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Our Shared Hosting. We offers Windows hosting starts from $5/month only. We also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable Windows Shared Hosting, we should be your best choice.



ASP.NET MVC Hosting - ASPHostPortal.com :: Simple Way to Upload File in ASP.NET MVC 4.0 Razor

clock October 19, 2015 19:00 by author Dan

In this tutorial I will show you how to upload a files in ASP.NET MVC 4.0. So how to do this?? Lets get start. Create a new MVC 4.0 application and add a new controller, name it as HomeController. We will use Index ActionMethod to write the code to upload the file.

We need two ActionMethod named Index, one is for HttpGet and another for HttpPost. Within the HttpGet ActionMethod we don't need to write anything.

Lets create the View first. To create the View right click on the ActionMethod Index and click on the Add View option.

In the View write down the code.

@{
    ViewBag.Title = "Upload file";
}

<h2>Upload File</h2>
<h3 style="color: green">@ViewBag.Message</h3>
@using (Html.BeginForm("Index", "Home", FormMethod.Post
            , new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary();

    <input type="file" id="fileToUpload" name="file" />
    <span class="field-validation-error" id="spanfile"></span>

    <input type="submit" id="btnSubmit" value="Upload" />
}


Here we have taken a simple HTML file up loader and a submit button. Within the form we are calling the ActionMethod Index, which is present in HomeController. A ValidationSummary to show all validation message.

Now get back to the ActionMethod. Within the Index ActionMethod (HttpPost) write down the code.

[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
      if (ModelState.IsValid)
      {
           if (file == null)
           {
              ModelState.AddModelError("File", "Please Upload Your file");
           }
           else if (file.ContentLength > 0)
           {
              int MaxContentLength = 1024 * 1024 * 4; //Size = 4 MB
              string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".pdf" };
           if (!AllowedFileExtensions.Contains
(file.FileName.Substring(file.FileName.LastIndexOf('.'))))
           {
                 ModelState.AddModelError("File", "Please file of type: " + string.Join(", ", AllowedFileExtensions));
           }
           else if (file.ContentLength > MaxContentLength)
           {
                 ModelState.AddModelError("File", "Your file is too large, maximum allowed size is: " + MaxContentLength + " MB");
            }
            else
            {
                 var fileName = Path.GetFileName(file.FileName);
                 var path = Path.Combine(Server.MapPath("~/Upload"), fileName);
                 file.SaveAs(path);
                 ModelState.Clear();
                 ViewBag.Message = "File uploaded successfully. File path :   ~/Upload/"+fileName;
             }
         }
     }
     return View();
}


Before run this project don't forget to create a Upload folder within root directory, otherwise you will get an error.

HttpPostedFileBase file getting the file which you are uploading.

file.ContentLength : Size of the file
file.FileName : file name with extension

Now run your project and enjoying your uploading.

Best Windows Shared Hosting Recommendation

ASPHostPortal.com provides our customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Our Shared Hosting. We offers Windows hosting starts from $5/month only. We also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable Windows Shared Hosting, we should be your best choice.



ASP.NET Hosting - ASPHostPortal.com : Dynamically Create Meta Description Using ASP.NET

clock October 13, 2015 08:37 by author Kenny

Dynamically Create Meta Description Using ASP.NET

HTML “meta description” allows us to describe web pages with short and sometimes elaborated details. Descriptions written inside the <meta> tag, must always to specific and are often limited to very few characters. Using Asp.Net, we can easily create “meta” descriptions dynamically, through code behind procedures, describing the contents of the page.

We all know how important it is to use meta tags when you’re building an internet web site. Meta tags provide metadata about the HTML document. They are not rendered in the browser but are used by search engines to parse web pages. The following article demonstrates how to store meta tags for each page in an XML file and how to use LINQ to read the XML data and dynamically create meta tags for each page in your website.

Open Visual Studio 2008 and choose File > New > Web > ASP.NET Web Application.

Add a Master Page to the project. Once that is completed, add a Web Content Page and select the newly created Master Page as the Master Page.

The next step is to create a new folder in the web site to demonstrate all pages in the website will have dynamic meta tags at runtime. Right click the website and choose Add > New Folder. Name the new folder ChildFolder. After this add a new Web Content Page to this folder. Leave the default name as this is not important.

Now that we have two pages in different folders, it’s now time to create an XML file that contains the data for the meta tags. Right click the website and choose Add > New Item > XML File. Name the file TagData.xml and add the following XML:

<metaTags>
 <tags pageName="/WebForm1.aspx">
    <tag name="keyword" value="This is a keyword"></tag>
    <tag name="description" value="This is a description"></tag>
    <tag name="author" value="malcolm sheridan"></tag>
 </tags>
 <tags pageName="/ChildFolder/WebForm1.aspx">
    <tag name="keyword" value="This is a keyword for the child pages"></tag>
    <tag name="description" value="This is a description for the child pages"></tag>
    <tag name="author" value="malcolm sheridan for this page too"></tag>
 </tags>
</metaTags>

In the XML above I have created a parent node called metaTags. Inside I have created a tags node which contains a pageName attribute. That value is how we will match the current requested page to the XML data. Each tags node contains a tag node that corresponds to the meta data we want sent to the browser. In this example I want to set meta tags for the all the pages to have keyword, description and author meta tags, but the values rendered to the browser will differ depending on what page the user is on. In a real world scenario this information would be stored inside a database, but I decided to keep this data inside an XML file to keep it simple and focus on how to do this.

Having outlined what meta tags we want sent to the browser, we now have to write the code that will read the XML file and dynamically add the meta tags at runtime. Seeing as though we’re using Master Pages this is the ideal spot to add it. Add the following code to read the XML file:

C#

XDocument doc = XDocument.Load(Server.MapPath("~/TagData.xml"));
var metaTags = doc.Descendants("tag")
              .Where(o => o.Parent.Attribute("pageName").Value == Request.Url.AbsolutePath)
               .Select(o => new
               {
                    Value = o.Attribute("value").Value,
                    Name = o.Attribute("name").Value
               });

VB.NET

Dim doc As XDocument = XDocument.Load(Server.MapPath("~/TagData.xml"))
Dim metaTags = doc.Descendants("tag").Where(Function(o) o.Parent.Attribute("pageName").Value = Request.Url.AbsolutePath).Select(Function(o) New With {Key .Value = o.Attribute("value").Value, Key .Name = o.Attribute("name").Value})

For flexibility and ease of use I have decided to use the power of LINQ to XML to read the XML data. To start with the XML document is load into an XDocument object. From there I have created a LINQ query to return all the tag nodes where the parent node has an attribute called pageName and the value is equal to the current page.   Then the object returned is an anonymous type that has a Value and Name property. The values of those properties are the value and name attribute values.

Now that we have the data in memory, the next step is to create the meta tag and add it to the page dynamically. To do this you use the HtmlMeta class. This allows you programmatic access to the HTML meta tags. Add the following code below to your project:

C#

foreach (var item in metaTags)
{              
     HtmlMeta meta = new HtmlMeta();
     meta.Name = item.Name;
     meta.Content = item.Value;
     Page.Header.Controls.Add(meta);
}

VB.NET

For Each item In metaTags
       Dim meta As New HtmlMeta()
       meta.Name = item.Name
       meta.Content = item.Value
       Page.Header.Controls.Add(meta)
Next item

The foreach loop enumerates through each item returned from the LINQ query. It assigns the Name and Content value to the HtmlMeta object. Finally the object is added to the page by calling Page.Header.Controls.Add(meta). Run the project and once the default page has loaded, view the HTML source and you’ll see the meta tags have been added to the website.

MetaTags

Browsing to the second page and viewing the HTML source, you’ll find the meta tags have been added to the page but they’re different values from the previous page.

Best Windows Shared Hosting Recommendation

ASPHostPortal.com provides our customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Our Shared Hosting. We offers Windows hosting starts from $5/month only. We also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable Windows Shared Hosting, we should be your best choice.



ASP.NET Hosting - ASPHostPortal.com :: How to Remove Html Tags from a String in ASP.NET

clock October 12, 2015 07:47 by author Dan

When we update content using WYSIWYG HTML editor (ck-editor) then it used HTML tag for formatting the content. But some time we need the same content without any formatting so then we require the removing HTML tag from that content.

Here I use two variation for this first one is using a simple loop And Second one is using Regex.

// How convert a html tag to blank space in a string using c#.net/asp.net code
// Replacing the html tag <> to blank space, you can copy data with html tag and then convert to normal text
// eg. INPUT   -->  <div width="5">Testing <i>Testing</i></div>
        OUTPUT--> Testing Testing
//
//C#.NET , ASP.NET

Method 1 : (Using Character Array)

 public string replace(string s)
 {
    int l = s.Length;
    int j = 0;
    char[] ch = s.ToCharArray();
    s = "";
    for (int i = 0; i < l; i++)
    {
        if (ch[i] == '<')
            j = 1;
        if (j == 1)
        {
            if (ch[i] == '>')
                j = 0;
            ch[i] = ' ';
        }
        s = s + ch[i].ToString();
    }
    return (s);
 }

Method 2 (Using Regular Expressions- Regex)

 using System.Text.RegularExpressions;
 public string replace(string s)
 {
   String result = Regex.Replace(s, @"<[^>]*>", String.Empty);
 }

Finish.. Happy Codiing..

Best Windows Shared Hosting Recommendation

ASPHostPortal.com provides our customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Our Shared Hosting. We offers Windows hosting starts from $5/month only. We also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable Windows Shared Hosting, we should be your best choice.



SQL 2014 Hosting - ASPHostPortal :: How to Optimize Your SQL Query

clock October 6, 2015 08:59 by author Jervis

Modern day software applications have millions of concurrent users. Development of an efficiently serviceable application requires a huge amount of effort and requires many tools and techniques. Software developers always try to improve the performance of the application by improving design, coding and database development. For database development, query optimization and evaluation techniques are playing vital parts.

Selection of required field only.

It is very important to avoid unnecessary data selection of the query. We should select a data field that we need but not all fields of the table.

SELECT login_id, pawwsord FROM tbluser  

Index

Properly created Indexes help to optimize search results. You need to better understand the databases before the selection of a better performing index. The selection of a highly used field as an index is very important.

CREATE clustered INDEX ind_login_id ON tbluser(login_id)  

Primary Key

The Primary Key is the most important index of the table. The most important thing about a Primary Key is the selection of a short and unique field. This will lead to easy access to the data records.

CREATE TABLE tbluser(
  id INT,  
  name VARCHAR(150),  
  email VARCHAR(100),  
  login_id VARCHAR(100),  
  password VARCHAR(10),  
  primary_key(id)  
)

Index unique column

The indexing of a unique column will improve searching and increase the efficiency of the database. You must have a better understanding of the data field and their utilization before indexing a unique column. The indexing of a less used column does not help improve the efficiency of the database.

CREATE INDEX ind_email ON tbluser(email)  

Select limited records

None of the user interfaces can visualize thousands of records at once. Hence there is no way to select all the records at once, so always limit the selection when you have a large number of records. Select the required data only.

SELECT id, name, email, login_id,password FROM tbluser WHERE 1 limite 10  

Selection of correct data type and length

Use the most appropriate data type and correct length of the data. The bad selection of a data type will produce bulky databases and poor performance. This will improve resource utilization of the database server.

CREATE TABLE tbluser(id INT,  
   name VARCHAR(150),  
   email VARCHAR(100),  
   login_id VARCHAR(100),  
   password VARCHAR(10)  
)  

Avoid in sub query

Always avoid use of IN sub-queries in your applications. An In sub-query will evaluate all the records of table A with table B (product of records) before selecting the required data.

SELECT login_id,name, email FROM tbluser WHERE login_id IN ( SELECT login_id FROM tbllogin_details)

One of the correct ways is to use an inner join as in the following:  

SELECT login_id,name, email FROM tbluser INNER JOIN tbllogin_details ON tbluser.login_id =tbllogin_details.login_id 

Avoid NOT operator

Please avoid the usage of the NOT operator situation that the number of qualifying records are lower than unqualified records. Always use a positive operator such as LIKE, EXIST than NOT LIKE, NOT EXIST.

SELECT * FROM tbluser WHERE email NOT LIKE '%gmail%'  

The prefered way is:

SELECT * FROM tbluser WHERE email LIKE '%yahoo%'  



About ASPHostPortal.com

We’re a company that works differently to most. Value is what we output and help our customers achieve, not how much money we put in the bank. It’s not because we are altruistic. It’s based on an even simpler principle. "Do good things, and good things will come to you".

Success for us is something that is continually experienced, not something that is reached. For us it is all about the experience – more than the journey. Life is a continual experience. We see the Internet as being an incredible amplifier to the experience of life for all of us. It can help humanity come together to explode in knowledge exploration and discussion. It is continual enlightenment of new ideas, experiences, and passions


Author Link


Corporate Address (Location)

ASPHostPortal
170 W 56th Street, Suite 121
New York, NY 10019
United States

Sign in