European ASP.NET MVC 4 and MVC 5 Hosting

BLOG about ASP.NET MVC 3, ASP.NET MVC 4, and ASP.NET MVC 5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

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.

 



European ASP.NET MVC 5 Cloud Hosting - Austria :: Implementation ASP.NET MVC 5 Authentication Filters

clock June 5, 2014 09:01 by author Scott

ASP.NET MVC 5 offer many great new features. In today post, I will share one of the new ASP.NET MVC 5 feature which is called Authentication Filters and ASP.NET identity Management. ASP.NET MVC does not provide any built-in authentication filter(s). However it provides you with the framework, so you can easily create your own custom authentication filters.

 

In previous ASP.NET MVC 4, maybe you use AuthorizationFilters. New authentication filters run prior to authorization filters. It is also worth noting that these filters are the very first filters to run before any other filters get executed.

Why Use Authentication Filters?

Prior to authentication filters, developers used the Authorization filters to drive some of the authentication tasks for the current request. It was convenient because the Authorization filters were executed prior to any other action filters.  For example, before the request routes to action execution, we would use an Authorization filter to redirect an unauthenticated user to a login page. Another example would be to use the Authorization filter to set a new authentication principal, which is different from the application’s original principal in context.

Authentication related tasks can now be separated out to a new custom authentication filter and authorization related tasks can be performed using authorization filters. So it is basically about separating of concerns, while giving developers more flexibility to drive authentication using ASP.NET MVC infrastructure.

The Implementation ASP.NET MVC Authentication Filters

If you've done any development with ASP .NET MVC, you've more than likely used the Authorization attribute to enforce role-based security within your Web site. With MVC 5, you can now apply an Authentication filters to your controller to allow users to authenticate to your site from various third-party vendors or a custom authentication provider.

When applied to an entire controller class or a particular controller action, Authentication filters are applied prior to any Authorization filters. Let's see an Authentication filter in practice. Create a new C# ASP .NET Web Application, see Figure below.

Then, select ASP.NET project type.

Let's first look at how to implement a custom authentication filter that will simply redirect the user back to the login page if they're not authenticated. Create a new directory named CustomAttributes in your project. Next, create a new class named CustomAttribute that inherits from ActionFilterAttribute and IAuthenticationFilter:

public class BasicAuthAttribute: ActionFilterAttribute, IAuthenticationFilter

The IAuthenticationFilter interface defines two methods: OnAuthentication and OnAuthenhenticationChallenge. The OnAuthentication method is executed first and can be used to perform any needed authentication. The OnAuthenticationChallenge method is used to restrict access based upon the authenticated user's principal.

 For this simple example, I'll only be implementing the OnAuthenticationChallenge method and will leave the OnAuthenitcation method blank:

public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
    var user = filterContext.HttpContext.User;
    if (user == null || !user.Identity.IsAuthenticated)
    {
        filterContext.Result = new HttpUnauthorizedResult();
    }
}

Here's the complete BasicAuthAttribute implementation:

using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace VSMMvc5AuthFilterDemo.CustomAttributes
{
    public class BasicAuthAttribute : ActionFilterAttribute, IAuthenticationFilter
    {
        public void OnAuthentication(AuthenticationContext filterContext)
        {
        }

        public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
        {
            var user = filterContext.HttpContext.User;
            if (user == null || !user.Identity.IsAuthenticated)
            {
                filterContext.Result = new HttpUnauthorizedResult();
            }
        }
    }
}

You can now test out the BasicAuthAttribute by applying it to the HomeController class. Open up the HomeController class file, then add a using statement for your CustomAttributes namespace:

using VSMMvc5AuthFilterDemo.CustomAttributes;

Then apply the custom attribute to the HomeController class:

[BasicAuthAttribute]
public class HomeController : Controller

When you run the application, you should now be automatically redirected to the login page

In order to view the homepage, you must register a user account

Once your user is registered, you'll be automatically redirected to the homepage

As you can see, it isn't overly complex to implement a custom authentication filter within ASP.NET MVC 5.

Summary

The new IAuthenticationFilter provides a great ability to customize authentication within an ASP.NET MVC 5 application. This provides a clear separation between authentication and authorization filters. OnAuthentication and OnAuthenticationChallenge methods provide greater extensibility points to customize authentication within ASP.NET MVC framework. We also looked at a sample usage of CustomAuthentication attribute and how you can use to change the current principal and redirect un authenticated user to a login page.



About HostForLIFE.eu

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

We have offered the latest Windows 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in