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

HostForLIFE.eu Proudly Launches Umbraco 7.5.7 Hosting

clock January 27, 2017 08:03 by author Peter

HostForLIFE.eu, a leading Windows web hosting provider with innovative technology solutions and a dedicated professional services team, today announced the support for Umbraco 7.5.7 hosting plan due to high demand of Umbraco users in Europe. The company has managed to build a strong client base in a very short period of time. It is known for offering ultra-fast, fully-managed and secured services in the competitive market.

 

HostForLIFE.eu hosts its servers in top class data centers that is located in Amsterdam, (NL), London, (UK), Washington, D.C. (US), Paris, (France), Frankfurt, (Germany), Chennai, (India), Milan, (Italy), Toronto, (Canada) and São Paulo, (Brazil) to guarantee 99.9% network uptime. All data centers feature redundancies in network connectivity, power, HVAC, security and fire suppression. All hosting plans from HostForLIFE.eu include 24×7 support and 30 days money back guarantee. HostForLIFE Umbraco hosting plan starts from just as low as €3.49/month only and this plan has supported ASP.NET Core 1.1, ASP.NET MVC 5/6 and SQL Server 2012/2014/2016.

Umbraco is a fully-featured open source content management system with the flexibility to run anything from small campaign or brochure sites right through to complex applications for Fortune 500's and some of the largest media sites in the world. Umbraco is strongly supported by both an active and welcoming community of users around the world, and backed up by a rock-solid commercial organization providing professional support and tools. Umbraco can be used in its free, open-source format with the additional option of professional tools and support if required.

Umbraco release that exemplifies our mission to continue to make Umbraco a bit simpler every day. The other change is that there's now a "ValidatingRequest" event you can hook into. This event allows you to "massage" any of the requests to ImageProcessor to your own liking. So if you'd want to never allow any requests to change BackgroundColor, you can cancel that from the event. Similarly if you have a predefined set of crops that are allowed, you could make sure that no other crop sizes will be processed than those ones you have defined ahead of time.

Further information and the full range of features Umbraco 7.5.7 Hosting can be viewed here: http://hostforlife.eu/European-Umbraco-757-Hosting



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Action Filter In MVC

clock January 26, 2017 07:43 by author Peter

Action filter in MVC provides the option to handle the situations after we would really like to perform an operation before and after the execution of a controller action. For this purpose, we create a custom class, which inherits the FilterAttribute class and implements the IActionFilter interface. when creating the filter, we simply apply the class name as an attribute on the controller.

Here, the FilterAttribute class makes it possible to use the class as an attribute and IActionFilter interface contains two methods named OnActionExecuting and OnActionExecuted. The OnActionExecuting is executed before the controller method is executed and OnActionExecuted is called after the execution of the controller method. This kind of technique is quite helpful for the logging purposes. Thus, let's see how we can use this filter.
 
Let's start by adding a new class named MyActionFilter.cs. Now, derive this class from the FilterAttribute and the IActionFilter. Implement the  OnActionExecuting and OnActionExecuted methods and add your custom logic into the methods.Thus, the code will look as shown below. 
    public class MyActionFilter : FilterAttribute, IActionFilter 
    { 
        public void OnActionExecuted(ActionExecutedContext filterContext) 
        { 
            //Fires after the method is executed 
        } 
     
        public void OnActionExecuting(ActionExecutingContext filterContext) 
        { 
            //Fires before the action is executed 
        } 
    } 


Simply, apply the class as an attribute on the controller. Add debuggers on both the methods as well as the controller method.
    public class HomeController : Controller 
    { 
        [MyActionFilter] 
        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(); 
        } 
    } 


Run the Application and debug step by step to see the order of execution of the methods. First, the OnActionExecuting will be executed, then the controller method and finally the OnActionExecuted method.

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



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Button Loader Integration in ASP.NET MVC

clock January 19, 2017 08:29 by author Peter

Today, I will write about Button Loader Integration in ASP.NET MVC. User interaction & responsiveness are major aspects in any application. It is always good to tell the user that is happening in the application i.e. whether they have to wait for certain processing or they can proceed with another action,  etc.

Today, I shall be demonstrating the integration of a simple button loader plugin called Ladda, you can explore it more by visiting the website.

You can download the complete source code for this tutorial from here or you can follow step by step discussion below. The sample code is developed in Microsoft Visual Studio 2013 Ultimate.

Create new MVC web project and name it "ButtonLoader".

Download the Ladda plugin and incorporate its related JavaScript & CSS files into the project.

Create new controller under "Controller" folder and name it "LoaderController.cs".

Open "RouteConfig.cs" file under "App_Start" folder and change the default controller to "Loader" and action to "Index" as shown below.
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
    using System.Web.Mvc; 
    using System.Web.Routing; 
    namespace ButtonLoader 
    { 
        public class RouteConfig 
        { 
            public static void RegisterRoutes(RouteCollection routes) 
            { 
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
                routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new 
                { 
                    controller = "Loader", action = "Index", id = UrlParameter.Optional 
                }); 
            } 
        } 
    } 

Create new file "LoaderViewModels.cs" under "Models" folder and place the following code in it:
    using System.ComponentModel.DataAnnotations; 
    namespace ButtonLoader.Models 
    { 
        public class LoaderViewModel 
        { 
            [Required] 
            [Display(Name = "Text")] 
            public string Text 
            { 
                get; 
                set; 
            } 
        } 
    } 

Here, we have created a simple model for observing our loader effect.
Now, open "LoaderController.cs" file under "Controller" folder and replace it with the following code:
    //-----------------------------------------------------------------------  
    // <copyright file="LoaderController.cs" company="None"> 
    // Copyright (c) Allow to distribute this code.  
    // </copyright> 
    // <author>Asma Khalid</author> 
    //-----------------------------------------------------------------------  
    namespace ButtonLoader.Controllers 
    { 
        using System; 
        using System.Collections.Generic; 
        using System.Linq; 
        using System.Security.Claims; 
        using System.Threading; 
        using System.Threading.Tasks; 
        using System.Web; 
        using System.Web.Mvc; 
        using ButtonLoader.Models; 
        /// <summary> 
        /// Loader controller class.  
        /// </summary> 
        public class LoaderController: Controller 
        { 
            #region Index view method.#region Get: /Loader/Index 
            method. 
                /// <summary> 
                /// Get: /Loader/Index method.  
                /// </summary> 
                /// <returns>Return index view</returns> 
            public ActionResult Index() 
            { 
                try 
                {} 
                catch (Exception ex) 
                { 
                    // Info  
                    Console.Write(ex); 
                } 
                // Info.  
                return this.View(); 
            }#endregion# region POST: /Loader/Index 
                /// <summary> 
                /// POST: /Loader/Index  
                /// </summary> 
                /// <param name="model">Model parameter</param> 
                /// <returns>Return - Loader content</returns> 
                [HttpPost] 
                [AllowAnonymous] 
                [ValidateAntiForgeryToken] 
            public ActionResult Index(LoaderViewModel model) 
            { 
                try 
                { 
                    // Verification  
                    if (ModelState.IsValid) 
                    { 
                        // Sleep.  
                        Thread.Sleep(5000); // 5 sec.  
                        // Info.  
                        return this.Json(new 
                        { 
                            EnableSuccess = true, SuccessTitle = "Success", SuccessMsg = model.Text 
                        }); 
                    } 
                } 
                catch (Exception ex) 
                { 
                    // Info  
                    Console.Write(ex); 
                } 
                // Sleep.  
                Thread.Sleep(5000); // 5 sec.  
                // Info  
                return this.Json(new 
                { 
                    EnableError = true, ErrorTitle = "Error", ErrorMsg = "Something goes wrong, please try again later" 
                }); 
            }#endregion# endregion 
        } 
    } 
In the above code snippet, we have created a simple "HttpGet" & "HttpPost" methods to observer the behavior of the button loader. We have also placed a 5 sec delay in the post method at every response to observer the behavior of the button loader from server side as well.

Now, in "Views->Loader" folder create a new page called "Index.cshtml" and place the following code in it:
    @using ButtonLoader.Models  
    @model ButtonLoader.Models.LoaderViewModel  
    @{  
    ViewBag.Title = "ASP.NET MVC5 C#: Button Loader Integration";  
    }  
     
    <div class="row"> 
        <div class="panel-heading"> 
            <div class="col-md-8"> 
                <h3> 
                    <i class="fa fa-file-text-o"></i> 
                    <span>Bootstrap Modal with ASP.NET MVC5 C#</span> 
                </h3> 
            </div> 
        </div> 
    </div> 
    <div class="row"> 
        <section class="col-md-4 col-md-push-4"> 
            @using (Ajax.BeginForm("Index", "Loader", new AjaxOptions { HttpMethod = "POST", OnSuccess = "onLoaderSuccess" }, new { @id = "LoaderformId", @class = "form-horizontal", role = "form" }))  
            {  
                @Html.AntiForgeryToken()  
     
            <div class="well bs-component"> 
                <br /> 
                <div class="row"> 
                    <div class="col-md-12 col-md-push-2"> 
                        <div class="form-group"> 
                            <div class="col-md-10 col-md-pull-1"> 
                                @Html.TextBoxFor(m => m.Text, new { placeholder = Html.DisplayNameFor(m => m.Text), @class = "form-control" })  
                                @Html.ValidationMessageFor(m => m.Text, "", new { @class = "text-danger custom-danger" })  
                            </div> 
                        </div> 
                        <div class="form-group"> 
                            <div class="col-md-18"></div> 
                        </div> 
                        <div class="form-group"> 
                            <div class="col-md-4 col-md-push-2"> 
                                <div > 
                                    <button type="submit"  
                                        class="btn btn-warning ladda-button"  
                                        value="Process"  
                                        data-style="slide-down"> 
                                        <span class="ladda-label">Process</span> 
                                    </button> 
                                </div> 
                            </div> 
                        </div> 
                    </div> 
                </div> 
            </div> 
    }  
     
        </section> 
    </div> 
In the above code snippet, we have created a simple text input box and a button, for Ladda plugin to work however, you have to use following structure on button i.e.
    <button type="submit" class="btn btn-warning ladda-button" value="Process" data-style="slide-down"> 
        <span class="ladda-label">Process</span> 
    </button> 
Unfortunately, Ladda plugin does not work with input type buttons.

Under "Scripts" folder, create a new script called "custom-loader.js" and place the following code in it:
    $(document).ready(function() 
    { 
        Ladda.bind('.ladda-button'); 
        $("#LoaderformId").submit(function(event) 
        { 
            var dataString; 
            event.preventDefault(); 
            event.stopImmediatePropagation(); 
            var action = $("#LoaderformId").attr("action"); 
            // Setting.  
            dataString = new FormData($("#LoaderformId").get(0)); 
            contentType = false; 
            processData = false; 
            $.ajax( 
            { 
                type: "POST", 
                url: action, 
                data: dataString, 
                dataType: "json", 
                contentType: contentType, 
                processData: processData, 
                success: function(result) 
                { 
                    // Result.  
                    onLoaderSuccess(result); 
                }, 
                error: function(jqXHR, textStatus, errorThrown) 
                { 
                    //do your own thing  
                    alert("fail"); 
                    // Stop Button Loader.  
                    Ladda.stopAll(); 
                } 
            }); 
        }); //end .submit()  
    }); 
    var onLoaderSuccess = function(result) 
    { 
        if (result.EnableError) 
        { 
            // Clear.  
            $('#ModalTitleId').html(""); 
            $('#ModalContentId').html(""); 
            // Setting.  
            $('#ModalTitleId').append(result.ErrorTitle); 
            $('#ModalContentId').append(result.ErrorMsg); 
            // Show Modal.  
            $('#ModalMsgBoxId').modal( 
            { 
                backdrop: 'static', 
                keyboard: false 
            }); 
        } 
        else if (result.EnableSuccess) 
        { 
            // Clear.  
            $('#ModalTitleId').html(""); 
            $('#ModalContentId').html(""); 
            // Setting.  
            $('#ModalTitleId').append(result.SuccessTitle); 
            $('#ModalContentId').append(result.SuccessMsg); 
            // Show Modal.  
            $('#ModalMsgBoxId').modal( 
            { 
                backdrop: 'static', 
                keyboard: false 
            }); 
            // Resetting form.  
            $('#LoaderformId').get(0).reset(); 
        } 
        // Stop Button Loader.  
        Ladda.stopAll(); 
    } 

I have also combined modal here to display server response. The following piece of code will bind the button loader plugin with the button i.e.
    Ladda.bind('.ladda-button');  
So, whenever, I click the button the button loader will start. The following piece of code will stop the button loader effect whenever I receive a response from the server side:
    // Stop Button Loader.  
    Ladda.stopAll();  

   
Now, execute the application. I hope it works for you!

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



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: New Configuration and AppSetings for ASP.NET MVC 6

clock January 17, 2017 10:35 by author Scott

There’s a new place to put the app settings for your MVC6 ASP.NET Core application. Web.config is gone but the new solution is great, you get a dependency injected POCO with strongly typed settings instead!

New Settings File - appsettings.json

Instead of web.config, all your settings are now located in appsettings.json. Here’s what the default one looks like, though I’ve also added an AppSettings section:

{
  "AppSettings": {
    "BaseUrls": {
      "API": "https://localhost:44307/",
      "Auth": "https://localhost:44329/",
      "Web": https://localhost:44339/
    },
    "AnalyticsEnabled": true
  },
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-AppSettings1-ad2c59cc-294a-4e72-bc31-078c88eb3a99;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Verbose",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Notice that we’re using JSON instead of XML now. This is pretty great with one big exception, No Intellisense.

Create an AppSettings class

If you’re used to using ConfigurationManager.AppSettings["MySetting"] in your controllers then you’re out of luck, instead you need to setup a class to hold your settings. As you can see above I like to add an “AppSettings” section to the config that maps directly to an AppSettings POCO. You can even nest complex classes as deep as you like:

public class AppSettings
{
    public BaseUrls BaseUrls { get; set; }
    public bool AnalyticsEnabled { get; set; }
}

public class BaseUrls
{
    public string Api { get; set; }
    public string Auth { get; set; }
    public string Web { get; set; }
}  

Configure Startup.cs

Now that we have a class to hold our settings, lets map the data from our appsettings.json. You can do it in a couple of ways

Automatically bind all app settings:

public IServiceProvider ConfigureServices(IServiceCollection services)
{           
    services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
}

or if you need to alter or transform anything you can assign each property manually:

public IServiceProvider ConfigureServices(IServiceCollection services)
{           
    services.Configure<AppSettings>(appSettings =>
    {
        appSettings.BaseUrls = new BaseUrls()
        {
            // Untyped Syntax - Configuration[""]
            Api = Configuration["AppSettings:BaseUrls:Api"],
            Auth = Configuration["AppSettings:BaseUrls:Auth"],
            Web = Configuration["AppSettings:BaseUrls:Web"],
        };               

        // Typed syntax - Configuration.Get<type>("")
        appSettings.AnalyticsEnabled = Configuration.Get<bool>("AppSettings:AnalyticsEnabled");
    });
}

Using the settings

Finally we can access our settings from within our controllers. We’ll be using dependency injection, so if you’re unfamiliar with that, get ready to learn!

public class HomeController : Controller
{
    private readonly AppSettings _appSettings;

    public HomeController(IOptions<AppSettings> appSettings)
    {
        _appSettings = appSettings.Value;
    }

    public IActionResult Index()
    {
        var webUrl = _appSettings.BaseUrls.Web;

        return View();
    }
}

There are a few important things to note here:

The class we are injecting is of type IOptions<AppSettings>. If you try to inject AppSettings directly it won’t work.

Instead of using the IOptions class throughout the code, instead I set the private variable to just AppSettings and assign it in the constructor using the .Value property of the IOptions class.

By the way, the IOptions class is essentially a singleton. The instance we create during startup is the same throughout the lifetime of the application.

While this is a lot more setup than the old way of doing things, I think it forces developers to code in a cleaner and more modular way.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Extend ASP.NET MVC AuthorizeAttribute?

clock January 12, 2017 07:28 by author Peter

Today, I will show you how to Extend ASP.NET MVC AuthorizeAttribute and how to Unit Test with ControllerActionInvoker. The reason for extending the AuthorizeAttribute class is that we might decide to store user credential information in a variety of differently data sources such as Active Directory, a database, an encrypted text file, etc…Or we might add custom logic to authorize a user.

OK, now we have set up our premises, let’s dive straight into the code for the subclass of AuthorizeAttribute:
    namespace SecurityDemo.Classes 
    { 
        [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] 
        public class CustomAuthorizeAttribute: AuthorizeAttribute 
        { 
            public override voidOnAuthorization(AuthorizationContextfilterContext) 
            { 
                if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
                //the user is not allowed to execute the Action. An Unauthorized result is raised. 
                filterContext.Result = newHttpUnauthorizedResult(); 
                var roles = GetAuthorizedRoles(); 
                stringwindowLoginName = filterContext.HttpContext.User.Identity.Name; 
                //windowLoginName and ADGroup is expected to have this format "ABC\\XYZ" 
                stringdomainName = windowLoginName.Contains(@ "\") ?windowLoginName.Substring(0, windowLoginName.IndexOf(@"\ 
                ", System.StringComparison.OrdinalIgnoreCase)) : windowLoginName; 
                windowLoginName = windowLoginName.Contains(@ "\") ? windowLoginName.Substring(windowLoginName.LastIndexOf(@ "\", System.StringComparison.OrdinalIgnoreCase) + 1): windowLoginName; boolisValidUser = false; 
                if (roles.Any(role => ADClass.IsUserInADGroup(windowLoginName, role.Substring(role.LastIndexOf(@ "\", System.StringComparison.OrdinalIgnoreCase) + 1), domainName))) //if window login belongs to AD group from config 
                { 
                    isValidUser = true; 
                } 
                elseif (roles.Any(role => windowLoginName.ToLower().Equals(role.Substring(role.LastIndexOf(@ "\", System.StringComparison.OrdinalIgnoreCase) + 1).ToLower()))) //if window login belongs to a user from config 
                { 
                    isValidUser = true; 
                } 
                if (isValidUser) 
                { 
                    return; 
                } 
                else 
                { 
                    HandleUnauthorizedRequest(filterContext); 
                } 
            } 
            protected override void HandleUnauthorizedRequest(AuthorizationContextfilterContext) 
            { 
                filterContext.Result = newViewResult 
                { 
                    ViewName = "~/Views/Shared/UnAuthorized.cshtml" 
                }; 
            } 
            //get list of authorized Active Directory groups and windows users from 
            // web.config 
            privateIEnumerable < string > GetAuthorizedRoles() 
            { 
                var appSettings = ConfigurationManager.AppSettings[this.Roles]; 
                if (string.IsNullOrEmpty(appSettings)) 
                { 
                    return new[] 
                    { 
                        "" 
                    }; 
                } 
                IEnumerable < string > rolesEnumerable = appSettings.Split(',').Select(s => s.Trim()); 
                return rolesEnumerable; 
            } 
        } 
    } 

 
In the sublassCustomAuthorizeAttribute above we override the OnAuthorization(Authorization Context filterContext) method and provide the logic to identify the windows login user, check the person against the list of authorized Active Directory groups and Windows users from web.config. We also override against the HandleUnauthorizedRequest(AuthorizationContextfilterContext) method to return a view for access denied. Of course, as mentioned, the authorization logic can be made as flexible and complex as possible according to specific business needs.

To use the extended attribute in a controller, we just apply to attribute to a method or class as in the below code snippet:
    public class ProductController: Controller 
    { 
        [CustomAuthorize(Roles = SystemRole.Administrators)] 
        public ActionResultIndex() 
        { 
            return View("Index"); 
        } 
        [CustomAuthorize(Roles = SystemRole.Administrators)] 
        public ActionResultDetails(int Id) 
        { 
            return View("Details"); 
        } 
    } 
    // a helper class to define roles 
    public class SystemRole 
    { 
        public const string Administrators = "Administrators"; 
        public cons tstring Sales = "Sales"; 
    } 

There we have it, we have come up with how to implement custom security as an attribute to be applied to a controller.

Unit Testing:
We can simply test our new security feature by launching the web application through the web browser after providing the access list in the web.config as mentioned in the beginning of the article. There is nothing wrong with that. However, if we need to get more fancy and methodical by doing some full unit testing using NUnit or Microsoft UnitTestFramework (which I’ll be using in this article) then there are a few challenges we’ll be facing. First is we’ll need to simulate a browser session with a full HttpContext with widows login, session, etc… and the way to do it is to use Mock object. The second challenge is how to invoke the action methods of a controller with our CustomAuthorizeAttribute applied. The way to do it is to extend a class calledControllerActionInvoker and override a method called InvokeActionResult(). Also if you need to invoke an action method with router parameters you also need to override the GetParameterValues() method as well. Well, one picture is worth a thousand words, so I present to you a “picture” of all the code (words) involved for the unit test:
    namespace UnitTestSecurityDemo 
    { 
        public class ActionInvokerExpecter < TResult > : ControllerActionInvokerwhereTResult: ActionResult 
        { 
            public boolIsUnAuthorized = false; 
            ///<summary> 
            /// override to get ViewName of controller in action 
            ///</summary> 
            ///<param name="controllerContext"></param> 
            ///<param name="actionResult"></param> 
            protected override voidInvokeActionResult(ControllerContextcontrollerContext, ActionResultactionResult) 
                { 
                    string viewName = ((System.Web.Mvc.ViewResult) actionResult).ViewName; 
                    IsUnAuthorized = viewName.ToLower().Contains("unauthorized"); 
                } 
                ///// <summary> 
                ///// override to get Routedata of controller in action 
                ///// </summary> 
                ///// <param name="controllerContext"></param> 
                ///// <param name="actionDescriptor"></param> 
                ///// <returns></returns> 
            protected overrideIDictionary < string, object > GetParameterValues(ControllerContextcontrollerContext, ActionDescriptoractionDescriptor) 
            { 
                return controllerContext.RouteData.Values; 
            } 
        } 
    } 
    namespace UnitTestSecurityDemo 
    { 
        [TestClass] 
        public class UnitTest1 
        { 
            [TestMethod] 
            public void TestIndexView() 
            { 
                var controller = new ProductController(); 
                MockAuthenticatedControllerContext(controller, @ "abc\jolndoe"); 
                ConfigurationManager.AppSettings.Set("Administrators", @ "abc\Group-ABC-App, abc\jolndoe1"); 
                ActionInvokerExpecter < ViewResult > a = newActionInvokerExpecter < ViewResult > (); 
                a.InvokeAction(controller.ControllerContext, "Index"); 
                Assert.IsTrue(a.IsUnAuthorized); 
            } 
            [TestMethod] 
            public void TestDetailsView() 
            { 
                //since the Details() action method of the controller has a router parameter, we need to pass 
                //router data in as below 
                var controller = newProductController(); 
                varrouteData = newRouteData(); 
                routeData.Values.Add("id", 3); 
                MockAuthenticatedControllerContextWithRouteData(controller, @ "abc\jolndoe", routeData); 
                ConfigurationManager.AppSettings.Set("Administrators", @ "abc\Group-ABC-App, abc\jolndoe"); 
                ActionInvokerExpecter < ViewResult > a = newActionInvokerExpecter < ViewResult > (); 
                a.InvokeAction(controller.ControllerContext, "Details"); 
                Assert.IsTrue(a.IsUnAuthorized); 
            } 
            private static void MockAuthenticatedControllerContext(ProductController controller, stringuserName) 
            { 
                HttpContextBasehttpContext = FakeAuthenticatedHttpContext(userName); 
                ControllerContext context = newControllerContext(newRequestContext(httpContext, newRouteData()), controller); 
                controller.ControllerContext = context; 
            } 
            private static void MockAuthenticatedControllerContextWithRouteData(ProductController controller, stringuserName, RouteDatarouteData) 
            { 
                HttpContextBasehttpContext = FakeAuthenticatedHttpContext(userName); 
                ControllerContext context = newControllerContext(newRequestContext(httpContext, routeData), controller); 
                controller.ControllerContext = context; 
            } 
            public static HttpContextBaseFakeAuthenticatedHttpContext(string username) 
            { 
                Mock < HttpContextBase > context = newMock < HttpContextBase > (); 
                Mock < HttpRequestBase > request = newMock < HttpRequestBase > (); 
                Mock < HttpResponseBase > response = newMock < HttpResponseBase > (); 
                Mock < HttpSessionStateBase > session = newMock < HttpSessionStateBase > (); 
                Mock < HttpServerUtilityBase > server = newMock < HttpServerUtilityBase > (); 
                Mock < IPrincipal > user = newMock < IPrincipal > (); 
                Mock < IIdentity > identity = newMock < IIdentity > (); 
                context.Setup(ctx => ctx.Request).Returns(request.Object); 
                context.Setup(ctx => ctx.Response).Returns(response.Object); 
                context.Setup(ctx => ctx.Session).Returns(session.Object); 
                context.Setup(ctx => ctx.Server).Returns(server.Object); 
                context.Setup(ctx => ctx.User).Returns(user.Object); 
                user.Setup(ctx => ctx.Identity).Returns(identity.Object); 
                identity.Setup(id => id.IsAuthenticated).Returns(true); 
                identity.Setup(id => id.Name).Returns(username); 
                returncontext.Object; 
            } 
        } 
    } 

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



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Binding and Minification in SiteCore MVC

clock January 6, 2017 07:01 by author Scott

This is a quick blog post on how to implement bundling and minification in Sitecore MVC project.  During development phase, it is always good to have multiple Javascripts and CSS files for better readability and maintainability of code.  But multiple Javascripts and CSS files degrade the performance of production website and also increase the load time of webpages as it requires multiple HTTP requests from browser to server.  Bundling and minification reduce the size of Javascript and CSS files and bundle multiple files into a single file and make the site perform faster by making fewer HTTP requests. Below steps explain how to implement bundling and minification for Sitecore MVC project: 

1. Add Microsoft ASP.NET Web Optimization Framework to your solution from nuget or run the following command in the Package Manager Console to install Microsoft ASP.NET Web Optimization Framework.

PM> Install-Package Microsoft.AspNet.Web.Optimization

2. Create your CSS and Javascript bundles in “BundleConfig” class under App_Start folder and add reference of "System.Web.Optimization" namespace.

public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            //js bundling using wildcard character *
            bundles.Add(new ScriptBundle("~/bundles/js").Include("~/assets/js/*.js"));

            //css bundling using wildcard character *
            bundles.Add(new StyleBundle("~/bundles/css").Include("~/assets/css/*.css"));
        }
    }

3. Register bundle in the Application_Start method in the Global.asax file. If you are using Multi-site instance of Sitecore MVC then recommend way to implement bundling logic is by creating a new processor into the initialize pipeline. 

protected void Application_Start(object sender, EventArgs e)
        {
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

We can override the value of the debug attribute in code by using EnableOptimizations property of the BundleTable class.

protected void Application_BeginRequest(object sender, EventArgs e)
        {
            EnableBundleOptimizations();
        }

        private void EnableBundleOptimizations()
        {
            string debugMode = Request.QueryString["debug"];
            if (!string.IsNullOrEmpty(debugMode) && string.Equals(debugMode, "true", StringComparison.InvariantCultureIgnoreCase))
            {
                BundleTable.EnableOptimizations = false;
            }
            else
            {
                BundleTable.EnableOptimizations = true;
            }
        }

Here in Application_BeginRequest method of Global.asax I am calling one custom method EnableBundleOptimizations() which sets the value of EnableOptimizations property to true or false based on value of querystring “debug”. Main idea behind this logic is that we can check/debug CSS or Javascript file on production by passing querystring parameter debug as true. 

5. Replace Javascripts and CSS references in layout or rendering view with below code:

@Styles.Render("~/bundles/css")
@Styles.Render("~/bundles/js")

6. In web.config set an ignore url prefix for your bundle so that Sitecore won’t try to resolve the URL to the bundle. Update setting IgnoreUrlPrefixes according to your bundle name:

<setting name="IgnoreUrlPrefixes" value="/sitecore/default.aspx|/trace.axd|/webresource.axd|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.DialogHandler.aspx|/sitecore/shell/applications/content manager/telerik.web.ui.dialoghandler.aspx|/sitecore/shell/Controls/Rich Text Editor/Telerik.Web.UI.SpellCheckHandler.axd|/Telerik.Web.UI.WebResource.axd|/sitecore/admin/upgrade/|/layouts/testing|/bundles/js|/bundles/css"/>

7. Now compile your solution and verify that bundling and minification is enabled by checking view source of webpage.

Pass querystring as debug=true in url and now verify view source of webpage. Bundling and minification is not enabled. This enables us to debug Javascript and CSS files in production website. 



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 2012 Hosting, ASP.NET 4.5 Hosting, ASP.NET MVC 5 Hosting, and SQL 2014 Hosting.


Tag cloud

Sign in