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 Germany - HostForLIFE.eu :: How To Combine Angular.js with ASP.NET MVC?

clock November 21, 2014 05:31 by author Peter

Angular is a superb resource, however it took me a few time to identify a method to combine it elegantly along with ASP.NET MVC. This is essentially how I made it happen. First, you must build a new ASP.NET MVC app. Next step, install the Angular package through NuGet. Now for the customization.

The goal is to make use of the normal ASP. NET MVC navigation, unless for certain URLs, when we will permit Angular get over. So, http://www.yourdomain.com/Account/Login could be managed by ASP. NET (" ASP.NET-mode "), however http://www.yourdomain.com/#/Customers could be dealt with by Angular (" Angular-mode "). In fact, it is ASP.NET serving us the Customers page, however after that, we wish to use Angular for data-binding, navigation, routing, the forms, and so on.

Add a new Controller along with one method, Index (), which returns View (). Standard ASP. NET up till currently. I named mine AngularController.Next, add a View inside the corresponding folder (in my case :/Angular/Index. cshtml). During this view, found out your primary Angular view. Some thing such as:
@{
    ViewBag.Title = "Index";

<div ng-app="app">
    <div ng-controller="main as vm">
        <div ng-view class="shuffle-animation"></div>
    </div>
</div> 
@section scripts {
    @Scripts.Render("~/bundles/angular")
}

Now, when I am in "Angular-mode", I want my ASP.NET MVC include with Angular scripts. The Angular bundle looks something such as: (in /App_Start/BundleConfig.cs):
bundles.Add(new Bundle("~/bundles/angular").Include(
                      "~/Scripts/angular.js",
                      "~/Scripts/angular-animate.js",
                      "~/Scripts/angular-route.js",
                      "~/Scripts/angular-sanitize.js",
                      "~/Scripts/app/app.js",
                      "~/Scripts/app/config.js",
                      "~/Scripts/app/main.js",
                      "~/Scripts/app/customers/customers.js"));


The explanation I am not using a ScriptBundle is because we don't need ASP.NET to minify the Angular scripts. This leads to errors as a result of Angular generally depends on function arguments being certain strings.

In the meantime, minification is not necessary, however inside a production-environment, you'd need to make use of the minified Angular scripts. In app.js, config. js and main. js, I have place the required code to obtain Angular running. The most significant component is the getRoutes function in config.js :
function getRoutes() {
    return [
        {
            url: '/customers',
            templateUrl: '/Scripts/app/customers/customers.html'
        }
    ];
}


Finally, the customers.html and customers.js include my Angular logic and HTML markup for that particular page. This currently lets you navigate to http://localhost:1578/Angular/#/ (your portnumber may differ of course).

There you've it. ASP.NET MVC is serving the HTML page which contains references to Angular scripts and templates, the browser downloads everything, after which Angular wires all of it along (In fact, you may wish to configure ASP. NET to make use of a totally different URL to the AngularController)

Adding the following code with your navigation is as easy as adding this tag within your _Layout. cshtml file:
<li><a href="https://www.blogger.com/Angular/#/customers">Customers</a></li>

Do not forget the hash. Next, lets add a second page. This'll build the distinction in among what I have been calling " ASP. NET-mode " and " Angular-mode " more clear. Add a new html file and also a new javascript file onto the/Scripts/app/customers/folder, add the route to config. js and add the javascript file in the Angular bundle in BundleConfig. cs. The link inside my case might currently be :
<a href="https://www.blogger.com/Angular/#/customers/create">Create new customer</a>

Next step, whenever you operate the app, navigating from/Angular/#/customers to, say,/Account/Login can load the complete new page. However navigating from/Angular/#/customers to/Anguler/#/customers/create stays inside Angular, and merely loads the new template, " staying within " your SPA. You are able to sort of notice as a result of loading a new page " within " the SPA feels faster. So, we have effectively combined ASP. NET MVC along with Angular.js, allowing us to select where we want/need that.

 



ASP.NET MVC 6 Hosting with Paris (France) Server - HostForLIFE.eu :: Fixing Cached Values when Update Posted Form Values on Postback with ASP.MVC

clock November 18, 2014 08:56 by author Peter

While focusing on a project I encountered a wierd issue on my ASP.NET MVC 6. I produced an easy registration form which posted to my controller method, that obtained a view design like a parameter. Inside my method I had the need to update the values for this View Model prior to passing it to the user through a similar View. But, this really is exactly in which I encountered " strange " outcomes. Regardless of the correct data binding, correct code updating the design values, and also the correct design becoming passed straight into the view, front-end users still obtained the recent form values they initially posted.

This was initially puzzling, because I can notice the model I'd been passing in was the right way up to date. Initially I assumed it was actually some type of caching issue and tried numerous choices, however to no avail. Eventually I found out the matter was coming coming from the Razor Helper I'd been utilizing - specifically the EditorFor method (though this relates to any Razor helper method).

Let us have a closer look. Below is an easy registration view :
@model  posting.Controllers.Guest
 <h2>Register</h2>
 <p>Welcome...</p>
@using (Html.BeginForm())
{
    <table>
        <tr>
            <td>
                @Html.LabelFor(g => g.FirstName)
            </td>
            <td>
                @Html.EditorFor(g => g.FirstName)
            </td>
        </tr>
        <tr>
            <td>
                @Html.LabelFor(g => g.LastName)
            </td>
            <td>
                @Html.EditorFor(g => g.LastName)
            </td>
        </tr>
        <tr>
            <td>
                @Html.LabelFor(g => g.Highlight)
            </td>
            <td>
                @Html.EditorFor(g => g.Highlight)
            </td>
        </tr>
    </table>
    <input type="submit" />
}

Now, I set up 2 simple controller methods to demonstrate that error. public ActionResult Register()
{
      return View();
}
[HttpPost]
public ActionResult Register(Guest guest)
{
    guest.FirstName = "Peter";
    return View(guest);

}

The first register method is really a Get request that will returns a simple sign up form using a first name and last name. The 2nd method will be the Post version from the first methodology, which means the values our user enters directly into form are certain to get mapped to our Guest view model. For demonstration purposes, I'm changing all users' names to Peter. But, when you operate this and fill out the form, you may notice the name never comes again as Peter - it constantly comes again as no matter what the user entered. The explanation for right here is the EditorFor helper method. These helper ways retrieve their information from ModelState first, then due to model object which is passed in. ModelState is essentially metadata in regards to the current model assigned from the MVC Model Binder when a request is mapped into your controller. Therefore in case the ModelState presently has values mapped from the MVC Model Binder, Razor Helpers can use those. The answer to get this is easy.
[HttpPost]
public ActionResult Register(Guest guest)
{
    ModelState.Remove("FirstName");
    guest.FirstName = "Peter";
    return View(guest);
}

That is literally all we need to do - this'll eliminate the FirstName property value set from the default MVC Model Binder and permit our personal code to write down a whole new value. You may also clear out the complete ModelState directly, as noticed beneath :
[HttpPost]
public ActionResult Register(Guest guest)
{
    ModelState.Remove("FirstName");
    guest.FirstName = "Peter";
    return View(guest);
}

This is a very simple issue however could be terribly frustrating in case you do not know what is happening.



ASP.NET MVC 6 Hosting with Paris (France) Server - HostForLIFE.eu :: Creating Calendar using ASP.NET MVC, Entity Framework and jQuery

clock November 14, 2014 05:22 by author Peter

Now, I we are going to learn how to create an  Event Calendar using ASP.NET MVC 6, Entity Framework and jQuery Fullcalendar plugin. First thing, that you have to do is Install the full calendar plugin using the Nuget Package Manager with the following command:

Install-Package jQuery.Fullcalendar

After that you'll be able to either add the scripts inside the BundleConfig. cs or you could reference all of these immediately in the _Layout. cshtml page (Master Page)
//Calendar css file
            bundles.Add(new StyleBundle("~/Content/fullcalendarcss").Include(
                     "~/Content/themes/jquery.ui.all.css",
                     "~/Content/fullcalendar.css"));
            //Calendar Script file
            bundles.Add(new ScriptBundle("~/bundles/fullcalendarjs").Include(
                      "~/Scripts/jquery-ui-1.10.4.min.js",
                      "~/Scripts/fullcalendar.min.js"));
@ViewBag.Title - My ASP.NET Application
    @Styles.Render("~/Content/css")
    @Styles.Render("~/Content/fullcalendarcss")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/fullcalendarjs")


Currently Determine the full calendar in the Home/Index.cshtml page. We really need to outline the calendar along with page identity therefore build a div with all the id “calendar”
<div id=”calendar”></div>

Then, you must add the code below, in the Home controller:
public ActionResult GetEvents(double start, double end)
        {
            var fromDate = ConvertFromUnixTimestamp(start);
            var toDate = ConvertFromUnixTimestamp(end);
            //Get the events
            //You may get from the repository also
            var eventList = GetEvents();
            var rows = eventList.ToArray();
            return Json(rows, JsonRequestBehavior.AllowGet);
        }
        private List GetEvents()
        {
            List eventList = new List();
            Events newEvent = new Events{
                id = "1",
                title = "Event 1",
                start = DateTime.Now.AddDays(1).ToString("s"),
                end = DateTime.Now.AddDays(1).ToString("s"),
                allDay = false
            };
            eventList.Add(newEvent);
            newEvent = new Events
            {
                id = "1",
                title = "Event 3",
                start = DateTime.Now.AddDays(2).ToString("s"),
                end = DateTime.Now.AddDays(3).ToString("s"),
                allDay = false
            };
            eventList.Add(newEvent);
            return eventList;       
}      
private static DateTime ConvertFromUnixTimestamp(double timestamp)
        {          
            var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return origin.AddSeconds(timestamp);
        }
Now, Make an Events class under the Models folder:
public class Events
    {
        public string id { get; set; }
        public string title { get; set; }
        public string date { get; set; }
        public string start { get; set; }
        public string end { get; set; }
        public string url { get; set; }
        public bool allDay { get; set; }
    }

Then Add the code below to your page:

@section scripts{
<script type=”text/javascript”>// <![CDATA[
$(document).ready(function () {
$('#calendar').fullCalendar({
theme: true,

defaultView: 'agendaDay',
editable: false,
events: "/home/getevents/"
});
});
// ]]></script>
}



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Duplicate Controller Names in ASP.NET MVC Areas ?

clock November 11, 2014 07:02 by author Peter

By convention, ASP.NET MVC 6 applications use HomeController to discuss with the controller that handles requests created to the root of the application. this can be designed by default with the subsequent route registration:

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

If you choose to partition your application using the ASP.NET MVC Areas feature, it’s commonplace that you simply would need calls to the root of every space to be handled employing a similar convention, via a HomeController.  However, if you add a HomeController to a part (for instance, an Admin area), you'll find yourself faced with this exception:

Multiple types were found that match the controller named ‘Home’. This can happen if the route that services this request (‘{controller}/{action}/{id}’) does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the ‘MapRoute’ method that takes a ‘namespaces’ parameter.

The request for ‘Home’ has found the following matching controllers:
AreaDemo.Areas.Admin.Controllers.HomeController
AreaDemo.Controllers.HomeController

Unfortunately by default you can not have duplicate controller names in ASPNET MVC Areas (or between a part and also the root of the application). fortunately, the fix for this can be pretty easy, and also the exception describes the step you wish to require.  Once you’ve added a part, you may have 2 completely different places (by default) wherever routes are defined: one in your root application and one in your area registration. you may need to regulate each of them to specify a namespace parameter. the root registration will change to one thing like this:
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    namespaces: new string[] {"AreaDemo.Controllers"}
);

Likewise, at intervals the AdminAreaRegistration.cs class, the default RegisterArea methodology feels like this:
public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Admin_default",
        "Admin/{controller}/{action}/{id}",
        new { action = "Index", id = UrlParameter.Optional}
        );
}

To adjust it to support a default HomeController and namespaces, it ought to be updated like so:
public override void RegisterArea(AreaRegistrationContext context)
{
    context.MapRoute(
        "Admin_default",
        "Admin/{controller}/{action}/{id}",
        new { controller="Home", action = "Index", id = UrlParameter.Optional},
        new string[] {"AreaDemo.Areas.Admin.Controllers"}
        );
}

With that changes in place, you must currently be ready to support the HomeController convention at intervals your MVC Areas, with duplicate controller names between areas and also the root of the applying.



HostForLIFE.eu Windows Hosting Proudly Launches New Data Center in Paris (France)

clock November 10, 2014 10:57 by author Peter

HostForLIFE.eu, a leading Windows web hosting provider with innovative technology solutions and a dedicated professional services team proudly announces New Data Center in Paris (France) for all costumers. HostForLIFE’s new data center in Paris will address strong demand from customers for excellent data center services in Europe, as data consumption and hosting services experience continued growth in the global IT markets.

The new facility will provide customers and our end users with HostForLIFE.eu services that meet in-country data residency requirements. It will also complement the existing HostForLIFE.eu. The Paris (France) data center will offer the full range of HostForLIFE.eu web hosting infrastructure services, including bare metal servers, virtual servers, storage and networking.

HostForLIFE.eu expansion into Paris gives us a stronger European market presence as well as added proximity and access to HostForLIFE.eu growing customer base in region. HostForLIFE.eu has been a leader in the dedicated Windows & ASP.NET Hosting industry for a number of years now and we are looking forward to bringing our level of service and reliability to the Windows market at an affordable price.

The new data center will allow customers to replicate or integrate data between Paris data centers with high transfer speeds and unmetered bandwidth (at no charge) between facilities. Paris itself, is a major center of business with a third of the world’s largest companies headquartered there, but it also boasts a large community of emerging technology startups, incubators, and entrepreneurs.

Our network is built from best-in-class networking infrastructure, hardware, and software with exceptional bandwidth and connectivity for the highest speed and reliability. Every upstream network port is multiple 10G and every rack is terminated with two 10G connections to the public Internet and two 10G connections to our private network. Every location is hardened against physical intrusion, and server room access is limited to certified employees.

All of HostForLIFE.eu controls (inside and outside the data center) are vetted by third-party auditors, and we provide detailed reports for our customers own security certifications. The most sensitive financial, healthcare, and government workloads require the unparalleled protection HostForLIFE.eu provides.

Paris data centres meet the highest levels of building security, including constant security by trained security staff 24x7, electronic access management, proximity access control systems and CCTV. HostForLIFE.eu is monitored 24/7 by 441 cameras onsite. All customers are offered a 24/7 support function and access to our IT equipment at any time 24/7 by 365 days a year.

For more information about new data center in Paris, please visit http://hostforlife.eu/Paris-Hosting-Data-Center

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

HostForLIFE.eu is awarded Top No#1 SPOTLIGHT Recommended Hosting Partner by Microsoft (see http://www.asp.net/hosting/hostingprovider/details/953). Our service is ranked the highest top #1 spot in several European countries, such as: Germany, Italy, Netherlands, France, Belgium, United Kingdom, Sweden, Finland, Switzerland and other European countries. Besides this award, we have also won several awards from reputable organizations in the hosting industry and the detail can be found on our official website.



ASP.NET MVC Hosting UK - HostForLIFE.eu :: How to Create ASPPDF Application with Classic ASP Hosting ?

clock November 7, 2014 08:29 by author Peter

ASPPDF is an active server part written by Persists package INC. With this part you'll dynamically produce, browse and modify portable Document Format (PDF) files. PDF is the de-facto world-wide commonplace for making and exchanging platform-independent printable documents. Giving your ASP.NET MVC / ASP.Net-based web applications the power to come up with and modify PDF documents on the fly opens endless opportunities for you and your users. Our initial application can produce a one-page PDF document, set its Title and Creator properties, and draw the phrase "Hello, World!" in giant helvetica letters across the page.

VBScript
Set Pdf = Server.CreateObject("Persits.Pdf")
Set Doc = Pdf.CreateDocument
Doc.Title = "ASPPDF Chapter 3 Hello World Sample"
Doc.Creator = "Peter"
Set Page = Doc.Pages.Add
Set Font = Doc.Fonts("Helvetica")
Params = "x=0; y=650; width=612; alignment=center; size=50"
Page.Canvas.DrawText "Hello World!", Params, Font
Filename = Doc.Save( Server.MapPath("hello.pdf"), False )
Response.Write "Success! Download your PDF file <A HREF=" & Filename & ">here</A>"

C#
IPdfManager objPdf = new PdfManager();
IPdfDocument objDoc = objPdf.CreateDocument(Missing.Value);
objDoc.Title = "ASPPDF Chapter 3 Hello World Sample";
objDoc.Creator = "Peter";
IPdfPage objPage = objDoc.Pages.Add(Missing.Value, Missing.Value, Missing.Value);
IPdfFont objFont = objDoc.Fonts["Helvetica", Missing.Value];
String strParams = "x=0; y=650; width=612; alignment=center; size=50";
objPage.Canvas.DrawText( "Hello World!", strParams, objFont );
String strFilename = objDoc.Save( Server.MapPath("hello.pdf"), false );
lblResult.Text = "Success! Download your PDF file <A HREF=" + strFilename + ">here</A>";


The primary line creates an instance of the PdfManager object, ASPPDF's top-level object. the subsequent line creates an empty PdfDocument object. The Pdf.CreateDocument technique accepts one optional argument, a document ID string. If no ID is specified , ASPPDF can generate a random one automatically. The document ID argument isn't used.
Doc.Title = "ASPPDF Chapter 3 hello World Sample"
Doc.Creator = "Peter"

That 2 lines above, will set the document's Title and Creator. These values may be viewed in acrobat Reader below File/Document Properties/Summary. different document properties which will be set via the PdfDocument object include Subject, Author, Keywords, Producer, CreationDate and ModDate.
Set Page = Doc.Pages.Add

This line adds a new page to the document. The Pages.Add technique accepts 3 optional arguments: width, Height (in PDF units, one unit equals 1/72 of an inch) and InsertBefore that controls the location of the new page among existing page (not applicable if the document is at the start empty).

By default, the page width and height are 612 and 792, severally, that corresponds to the quality 8.5" x 11" size.

If InsertBefore is omitted, the new page is added to the end of the document. If present, it should be a 1-based index of an existing page within the document.
Set Font = Doc.Fonts("Helvetica")

This line queries the Doc.Fonts collection for a desired font. The default parameterized Fonts..Item property expects a font name as the initial parameter, and a CharSet code because the second optional parameter.
Params = "x=0; y=650; width=612; alignment=center; size=50"
Page.Canvas.DrawText "Hello World!", Params, Font

These 2 lines show the text "Hello World!" in size fifty helvetica on the page. (The auxiliary string variable Params is used for readability functions only. The second argument to Canvas.DrawText might even be an initialized PdfParam object.)

Besides the text and font arguments, 5 numeric arguments are being passed to the DrawText technique. X and Y are always needed, the others are optional in most cases. during this case, text alignment is set to center that makes the width parameter required also.

Filename = Doc.Save( Server.MapPath("hello.pdf"), False )

This line saves the document to disk. the primary argument is required and should be set to a full file path. The second argument is optional. If set to True or omitted, it instructs the Save technique to write an existing file. If set to False, it forces distinctive file name generation. as an example, if the file hello.pdf already exists within the specified  directory and another document is being saved below the same name, the Save technique tries the filenames hello(1).pdf, hello(2).pdf, etc., till a non-existent name is found. The Save method returns the filename (without the path) below that the file was saved.

 



ASP.NET MVC 5 Hosting UK - HostForLIFE.eu :: Using the ASP.NET MVC 5 Filter Overrides Feature

clock October 28, 2014 09:04 by author Peter

In the previous post we took a glance at the new authentication filter and its strong points. There's an extra new filter that has been free with ASP.NET MVC 5 Hosting that was requested by several developers out their over a protracted time. This can be the new filter override feature! Within the previous versions of MVC, there was no thanks to override a filter for simply one action or controller. What you had to do is to use the filter for every and each action and controller one by one and this was an enormous waste of development time. Rather than doing this developers found ways to implement filter overrides using workaround. But usually the usage of workarounds cause the lack of code consistency. Therefore as an answer for this, Filter Overrides feature was introduced in MVC 5.

Filter Overrides in action

Imagine a situation where you want to exclude a globally applied authorization filter just only for a single action method. This was one thing you may not implement easily with the previous versions of MVC. however now the MVC 5 Filter Overrides feature provides you this capability with few lines of code. Lets have a glance at the following code snippet:

[Authorize(Users = "Admin")]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";
        return View();
    }
    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";
        return View();
    }
}

As you'll see AuthorizeAttribute has been embellished to the HomeController class with the user ‘Admin’. so it applies to all or any the actions within the controller. Assume you would like to bypass this filter only for the ‘About’ action. you would like to provide access to ‘About’ page just for user ‘Peter’ only. In MVC 5 you'll achieve this by adding 2 lines of code as illustrated in the following code snip.

 

OK. That’s it. currently all the actions inside the home Controller will only be accessed by ‘Admin’ except the ‘About’ action. The ‘About’ action is merely accessible for ‘Peter’. therefore now you'll get eliminate the headache of applying filters for every and each action wherever you would like to exclude only one or 2 actions.

There are 5 kinds of override filters accessible for every of filter types:

  1.     OverrideActionFilters
  2.     OverrideAuthentication
  3.     OverrideAuthorization
  4.     OverrideExceptionFilters
  5.     OverrideResultFilters

You will use the relevant override filters where is required.

Filter Override Bug Workaround

For making a bug workaround you'll have to do some of things:
Implement a custom class that may inherit from the action filter that you just wish to override and implement the IOverrideFilter. You’ll have to implement the FiltersToOverride property wherever you have got to identify the filters that you wish to override. for example lets create an easy workaround for the instance that has been described above:
public class MyOverrideAuthorizeAttribute : AuthorizeAttribute, IOverrideFilter
{
    public Type FiltersToOverride
    {
        get
        {
            return typeof(IAuthorizationFilter);
        }
    }
}

Then, the Controller implementation will change to:
[Authorize(Users = "Admin")]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    [MyOverrideAuthorize(Users = "Peter")]
    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";
        return View();
    }
    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";
        return View();
    }
}



European ASP.NET MVC 5 Hosting - UK :: Tips Improving Your ASP.NET MVC Codebase

clock October 27, 2014 10:05 by author Scott

Some of you sometimes think why your application eat up until 1 GB-2GB memory on production server. After looking through the code, doing some profiling, maybe shaking your head a bit, you've figured out what the issue is and now you need to give some feedback.

In this tutorial, I will show some tips that you can follow to reduce your memory usage on production server and keep your ASP.NET MVC codebase working as you’d expect.

1. Understand the queries in your problem domain

The root cause of the support ticket I received was a simple case of fetching too much data from the database, causing obscene amounts of memory usage.

It's a common enough issue. You're building a simple blog, it has posts and it has media (images, videos, attachments). You put a Media array onto your Post domain object. Your Media domain object has all the image data stored in a byte array. Since you're using an ORM, there's a certain way you need to design your domain model to play nice; we've all experienced this.

public class BlogPost {
    public ICollection<BlogMedia> Media { get; set; }
}
public class BlogMedia {
    public byte[] Data { get; set; }
    public string Name { get; set; }
}

There's nothing absolutely wrong with this design. You've modeled your domain accurately. The problem is, when you issue a query through your favorite ORM, it eagerly loads all the data associated with your blog post:

public IList<BlogPost> GetNewestPosts(int take) {
    return _db.BlogPosts.OrderByDescending(p => p.PostDate).Take(take).ToList();
}

A seemingly innocuous line (unless you've been bitten), a sneaky monster is lying in wait with big consequences if you haven't disabled lazy loading or didn't tell your ORM to ignore that big Data property on blog media.

It's important to understand how your ORM queries and maps objects and make sure you only query what you need (for example using projection).

public IList<PostSummary> GetNewestPosts(int take) {
    return _db.BlogPosts.OrderByDescending(p => p.PostDate).Take(take).Select(p => new PostSummary() {
        Title = p.Title,
        Id = p.Id
    }).ToList();
}

This ensures we only grab the amount of data we really need for the task.

It's OK to have more than 5 methods on a repository; be as granular as you need to be for your UI.

2. Don't call your repositories from your views

Consider this line in an MVC view:

@foreach(var post in Model.RelatedPosts) {
    ...
}

It seems innocent enough. But if we take a look at what exactly that model property is hiding:

public class MyViewModel {

    public IList<BlogPost> RelatedPosts {
        get { return new BlogRepository().GetRelatedPosts(this.Tags); }
    }

}

Your "view model" has business logic in it on top of calling a data access method directly. Now you've introduced data access code somewhere it doesn't belong and hidden it inside a property. Move that into the controller so you can wrangle it in and populate the view model conciously.

This is a good opportunity to point out that implementing proper unit tests would uncover issues like this; because you definitely can't intercept calls to something like that and then you'd realize injecting a repository into a view model is probably not something you want to be doing.

3. Use partials and child actions to your advantage

If you need to perform business logic in a view, that should be a sign you need to revisit your view model and logic. I don't think it's advisable to do this in your MVC Razor view:

@{
    var blogController = new BlogController();
}

<ul>
@foreach(var tag in blogController.GetTagsForPost(p.Id)) {
    <li>@tag.Name</li>
}
</ul>

Putting business logic in the view is a no-no, but on top of that you're creating acontroller! Move that into your action method and use that view model you made for what it's intended for. You can also move that logic into a separate action method that only gets called inside views so you can cache it separately if needed.

//In the controller:

[ChildActionOnly]
[OutputCache(Duration=2000)]
public ActionResult TagsForPost(int postId) {
    return View();
}

//In the view:

@{Html.RenderAction("TagsForPost", new { postId = p.Id });}

Notice the ChildActionOnly attribute. From MSDN:

Any method that is marked with ChildActionOnlyAttribute can be called only with the Action or RenderAction HTML extension methods.

This means people can't see your child action by manipulating the URL (if you're using the default route).

Partial views and child actions are useful tools in the MVC arsenal; use them to your advantage!

4. Cache what matters

Given the code smells above, what do you think will happen if you only cached your view model?

public ActionResult Index() {
    var homepageViewModel = HttpContext.Current.Cache["homepageModel"] as HomepageViewModel;

    if (homepageViewModel == null) {
        homepageViewModel = new HomepageViewModel();
        homepageViewModel.RecentPosts = _blogRepository.GetNewestPosts(5);

        HttpContext.Current.Cache.Add("homepageModel", homepageViewModel, ...);

    }

    return View(homepageViewModel);
}

Nothing! There will not be any performance gain because you're accessing the data layer through a controller variable in the view and through a property in the view model... caching the view model won't help anything.

Instead, consider caching the output of the MVC action instead:

[OutputCache(Duration=2000)]
public ActionResult Index() {
    var homepageViewModel = new HomepageViewModel();

    homepageViewModel.RecentPosts = _blogRepository.GetNewestPosts(5);

    return View(homepageViewModel);
}

Notice the handy OutputCache attribute. MVC supports ASP.NET Output Caching; use it to your advantage when it applies. If you are going to cache the model, your model needs to essentially be a POCO with automatic (and read-only) properties... not something that calls other repository methods.

Conclusion

I hope with tutorial above, it will help you to minimize your memory usage on the server.

 



ASP.NET MVC 5 Hosting UK - HostForLIFE.eu :: How to Easily Add ASP.NET MVC Anti-Forgery Tokens to any or all Post Requests

clock October 24, 2014 07:35 by author Peter

Today, I will show you How to Easily Add ASP.NET MVC 5 Anti-Forgery Tokens to any or all Post Requests. One of the newer attacks against web applications is that the cross-site request forgery attack. It’s an attack against modern applications that store a cookie to represent the presently logged in user. The matter has been explained in different websites.

One of the techniques to stop this attack is to add an anti-forgery token using the @Html.AntiForgeryToken extension technique. On the controller side, the action technique defines the [ValidateAntiForgeryToken] attribute. Behind the scenes, the hidden input field for the anti-forgery token is valid by the ASP.NET MVC  5 framework to confirm it’s correct. Whereas there's discussion as to whether or not this approach is required only for the logging in an anonymous posts, or all posts in general, as been up for debate. However the purpose of CSRF is to attack authenticated users.
public class GlobalAntiForgeryTokenAttribute
  : FilterAttribute, IAuthorizationFilter
{
  public sub OnAuthorization(filterContext As AuthorizationContext)
  {
                if (filterContext.HttpContext.Request.HttpMethod.ToUpper() == "POST")
                {
                  AntiForgery.Validate();
    }         
  }
}

On authorization of the request, if the operation may be a POST request, we tend to call the Validate() method on the AntiForgery helper to actually perform the validation. All of our post operations are currently checked for forgery; but, this can fail as a result of we haven’t added our token globally. To do that, we've to create a custom form extension method just like the following:

public static void FormExtensions
{
   public static MvcForm BeginDataForm(this HtmlHelper html, string action, string controller, ...)
  {
     var form = html.BeginForm(action, controller, ...);
                 //At this point, the form markup is rendered in BeginForm
                 // we can render the token       
                 //With every form, we render a token, since this
                 //assumes all forms are posts
                 html.ViewContext.Writer.Write(html.AntiForgeryToken().ToHtmlString());
                return form;
   }
}

If we use our custom helper for all of our forms, then all of our custom forms can have rendered an anti-forgery token. so we don’t have to worry about making it ourselves, saving time and reducing code.



ASP.NET MVC 5 Hosting UK - HostForLIFE.eu :: RegularExpression Validation Using Annotations in ASP.NET MVC 5

clock October 21, 2014 11:34 by author Peter

We can do Regular Expression or REGEX validation using Annotations in ASP.NET MVC 5. we can use "RegularExpression" attribute for validation. during this attribute we specify Regular Expression string. We can also specify our custom error messages for that we'd like to set "ErrorMessage" Property in "RegularExpression" attribute. Here is the example for this.

We take "Email" Address validation using REGEX. If user enter email address, which isn't in correct format at that time our validation message display on screen.
[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}",
        ErrorMessage="Email Address is not in proper format.")]
        public string Email { get; set; }

At the view side , add this code:
  @Html.EditorFor(model => model.Email)
        @Html.ValidationMessageFor(model => model.Email,"", new {  style="color:red"})

Here is Code for this. Model (Customer.cs):

public class Customer
    {
        public int CustomerID { get; set; }
        [Required]
        [StringLength(20,MinimumLength=2)]
        public string FirstName { get; set; }
        [StringLength(10)]
        public string LastName { get; set; }
        [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}",
        ErrorMessage="Email Address is not in proper format.")]
       public string Email { get; set; }
    }



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