There is a follow-up article about integration tests in 2016. Recommended for reading if you are using VSTS and looking at Cake build system

Unit tests are fine and dandy, but if you persist your data in database, persistence code must be tested as well. Some possible bugs will never be picked up only by unit tests. One of the issues I’ve been burned by is entity validation, another is a missing foreign key relationship.

Validation issues can burn you very easy. Look at this bit of code:

public class Person 
{
    [Key]
    public Guid PersonId { get; set; }

    [Required]
    public String FirstName { get; set; }

    [Required]
    public String LastName { get; set; }
}

public void CreatePerson(string firstName, string lastName)
{
    var newPerson = new Person();
    newPerson.FirstName = firstName;

    // dbContext was injected via constructor
    dbContext.Persons.Add(newPerson); 
    dbContext.SaveChanges();
}

NB: This is just a sample code. Nowhere in my projects we do such things.

Continue reading

We are hitting the deck with our site performance and optimisation. It is fast, but we want it uber-fast! So next stage is to have IIS up and active all the time with all the views being compiled and ready before any user comes to them.

By default, IIS compiles views only when a request for that view comes in. So first time a user visits some rare page in your application, user is waiting a bit longer while IIS does Just-In-Time compilation. And actually if you look under the hood IIS does stacks of things before it shows you a web-site.

Despite of common believe, IIS does not run your web-application from /bin folder, it copies all required files to a temp folder. To be more specific, it copies files to c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\. Reason for that – file locking. For just-in-time compilation, it needs to update binaries, but in /bin folder binaries can be locked.

Continue reading

HTTPS everywhere is a common theme of the modern infosys topics. Despite of that when I google for implementation of HTTPS in ASP.Net MVC applications, I find only a handful of horrible questions on StackOverflow, about how to implement HTTPS only on certain pages (i.e. login page). There have been numerous rants about security holes awaiting for you down that path. And Troy Hunt will whack you over your had for doing that!

See that link above? Go and read it! Seriously. I’ll wait.

Have you read it? Troy there explains why you want to have HTTPS Everywhere on your site, not just on a login page. Listen to this guy, he knows what he is talking about.

Continue reading

UPDATE: After initial excitement about xUnit, I needed to deal with some specifics. And now I don’t advise to move ALL your tests to xUnit. I’d recommend go into that slow and read through my rant here, before you commit to converting.

Nunit is a great testing framework. Only it is a little old now and new testing approaches are no longer fit into Nunit concepts. I’m talking about using Autofixture for generating test data. So I decided to see how xUnit will pan out for our projects and should we convert all our tests into xUnit or not.

Benefits of xUnit over NUnit are simple for me: AutoData attribute from Autofixture does not play nicely with NUnit due to architectural wirings. There are ways to have Autodata for
Nunit
, but this does not work nicely with Resharper 8.1 and NCrunch.

Continue reading

Before today I’ve heard of IlMerge tool. This allows you to bundle all your small .dll files into one. So if you deploy stand-alone applications, you only have to give a single file to your users. Today I decided to give it a go. And I was disappointed -( error messages were endless. IlMerge did not like this or that or some other assembly.

I quickly looked around and found Costura.Fody package that did exactly what I needed, only I did not have to do any work. All you need to do is install nuget package:

Install-Package Costura.Fody

And you are done. No, really. Build your project and check out the output. You’ll see a bunch of dll files as before. This is because input files are not deleted automatically. But if you check your executable – it is much larger now. And you can move it away from the rest of libraries files and it will work.

There are some settings available. Check the details on https://github.com/Fody/Costura.

Package installation will create FodyWeavers.xml file in the root of your solution – put your settings there. I needed to exclude debug symbols from the resulting file. Here is how my FodyWeavers.xml look like:

<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
  <Costura IncludeDebugSymbols='false' />
</Weavers>

Also I did not care about “minifying” the libraries into one file when I built the debug, but I needed it for Release build. So in my .csproj file, at the very end I have this:

  <Import Project="Fody.targets" Condition=" '$(Configuration)' == 'Release' " />
  <!-- Below is the clean-up - removing the input dll files-->
  <Target AfterTargets="AfterBuild;NonWinFodyTarget" Name="CleanReferenceCopyLocalPaths" Condition=" '$(Configuration)' == 'Release' ">
    <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
  </Target>

By default the package only adds one line:

  <Import Project="Fody.targets" />

And usually this is good enough. But I’ve added checking for build type and also my OCD required to produce a clean output folder. All this is explained on the GitHub page, on the very bottom.

Overall, very nice package! It just works.

I had a task of uploading files from command line client to a private container in Azure Blob Storage. And as part of the overall infrastructure I also has MVC4 and WebApi sites running on my Azure Web-Site installation.

The problem with uploading files was that the container was private. Before, every time I used the container, I used private key to access it, but all the operations were contained on the server: user submits a file in a form in a browser, file is passed through MVC web-site, where it is uploaded into Azure blob storage. And in MVC there is a very easy way to manage multiple uploaded files.

Now my task was similar, but as a client I had command line application and server side was WebApi. In WebApi it is not so easy to manage uploaded files, especially if you had multiple files for upload. You could not (or I could not find a way to do that) simply redirect the upload stream from controller into Azure Blob. You had to store file somewhere and then copy that to Azure storage. And there are a few problems with that:

Continue reading

Quartz.Net is an awesome scheduler for .Net world. It is a copy-cat from Java brother. The documentation is pretty useless, as it has not been updated for a while. The docs are useful to understand the general principals of operation, but examples of code usually don’t work. Instead the download provided on the site has a lot of examples. Use them as a guidance. Read the code, documentation sucks.

Anyway, I’ve spent couple days trying to get Quartz.Net to work inside of Azure and with Autofac dependency injection. And there are a few lessons that I’ve learned that I would like to share.

Continue reading

I’m working with Entity Framework a lot and sometimes you can get yourself tied into a knot so hard, you can’t figure out wtf is happening and why simple looking LINQ query leads to about 1K actual SQL requests. This is not good, so be careful with what you are doing there.

Today I had to untie one of these knots: a simple looking LINQ was producing horrible SQL requests and made many of them. Mostly due to poor legacy structure of the DB we have to battle at the moment. Anyway, it turned out that instead one massive LINQ to Objects, it was more performant to make 3 similar request to 3 similar tables in SQL Server. And all those requests were with similar .Where() conditions. And it looked like this:

var holidayMovements = this.HolidayMovements
    .Where (m => (startDate <= m.Start && m.Start <= endDate)
        || (startDate <= m.End && m.End <= endDate)     
        || (m.Start <= startDate && endDate <= m.End));

var absenceMovements = this.AbsenceMovements
    .Where (m => (startDate <= m.Start && m.Start <= endDate)   
        || (startDate <= m.End && m.End <= endDate)             
        || (m.Start <= startDate && endDate <= m.End));         

notice that in both cases .Where() clauses are identical? And I have 3 of these. I could live with 2 instances of the same condition, as later down the line it might turn up that 2 of the conditions are not really the same and you need to change one of them.. and if you DRY-it out into a method, you might end up with more crutches than you need without DRYing. But 3 instances are prime candidate for refactoring this out into a function/variable.

But how can you separate lambda expression into a separate variable? Like this:

Expression<Func<PersonnelMovementBase, bool>> timeBoundaryCondition = 
    m => (startDate <= m.Start && m.Start <= endDate)   
            || (startDate <= m.End && m.End <= endDate) 
            || (m.Start <= startDate && endDate <= m.End);

var holidayMovements = this.HolidayMovements
    .Where (timeBoundaryCondition);

var absenceMovements = this.AbsenceMovements
    .Where (timeBoundaryCondition);         

Now condition is the same in the separate queries and the LINQ query looks much more sane now. Quite simple to my mind, but it took me more than 3 minutes to figure out how to create a lambda expression outside of the .Where(), so here you go. Just don’t forget to look this up when you need similar thing again.

Sometimes in ASP.Net MVC you need to submit a form that will always go by GET method. But standard BeginForm() function does not have an override that does not requires specifying Controller and Action where you would like to submit the form back to. And sometimes you don’t want to specify where the form to go to, cause the same form can go into multiple controllers (think of a partial view). And default BeginForm() submits only by POST. So there is no default way to say I want to submit form by POST to wherever the form has came from.

I had to poke through MVC source code to figure out how to do what I want, and keep all the parameters and not mess up any paths. Here you go:

public static MvcForm BeginForm(this HtmlHelper htmlHelper, FormMethod method)
{
    var rd = htmlHelper.ViewContext.HttpContext.Request.RequestContext.RouteData;
    var currentAction = rd.GetRequiredString("action");
    var currentController = rd.GetRequiredString("controller");

    return htmlHelper.BeginForm(currentAction, currentController, rd.Values, method);
}

I had a task of creating a read-only user role in our MVC application. And given the limited time for the task I had to do that with minimal changes to the domain/architecture.

I have started with creating “Readonly” user role. Hopefully I don’t need to explain how to do that.

This is not the most elegant solution to the problem, but it kinda does the job. It block read-only user from using the POST actions, also if available substitutes Edit views with Details views (presuming this is CRUD application). Also we add javascript to Edit pages where we don’t have Details page.

Then I created a global filter:


    public class ReadOnlyFilter : IActionFilter 
    {
        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var currentUser = HttpContext.Current.User;
            if (currentUser == null || !currentUser.Identity.IsAuthenticated)
                return; // user is not logged in yet. Give them a break, please! Maybe they just trying to login. Not even touching your precious controllers yet!


            if (!currentUser.IsInRole("Readonly")) 
                return; // user is not read-only. Nothing to see here, move on!


            // Presume User is read-only from now on************************************

            var readOnlyAttribute = GetForReadOnlyUserAttribute(filterContext);

            // If DisableUserInput applied to the action, turn on JS for disabling the input fields on the view
            if (readOnlyAttribute != null && readOnlyAttribute.DisableInputFields)
                DisableInputOnForm(filterContext);

            // if AllowPost Attribute applied to the action, ignore the rest of this filter and get on with this
            if (readOnlyAttribute != null && readOnlyAttribute.AllowPost == true)
                return;

            // if action is of type post - deny
            if (filterContext.HttpContext.Request.HttpMethod.ToLower() == "post" )
            {
                ReadOnlyPage(filterContext);
                return;
            }

            // if action is "Create" - deny access
            if (filterContext.ActionDescriptor.ActionName.ToLower() == "create")
            {
                ReadOnlyPage(filterContext);
                return;
            }

            // if action is edit - check if Details action exits -> redirect to it.
            if (filterContext.ActionDescriptor.ActionName.ToLower() == "edit")
            {
                // find a method named Details that has exactly the same set of parameters as the request.
                var detailsAction = GetActionMethod(filterContext, "Details");

                // if "Details" action exist, we redirect the user into that action.
                if (detailsAction != null)
                {
                    // (in)sanity check. Also Resharper told me this could be null.
                    if (filterContext.HttpContext.Request.Url == null) return;

                    // simply replace the "Edit" with "Details" in a url. This is DIRTY, just the way I like my women: http://goo.gl/wrKuI
                    var currentUrl = filterContext.HttpContext.Request.Url.ToString();
                    var newUrl = currentUrl.Replace("Edit", "Details");

                    // and redirect to the new url.
                    filterContext.Result = new RedirectResult(newUrl);
                }
                else
                {
                    DisableInputOnForm(filterContext);
                }
            }
        }



        /// 
        /// Redirect user to read-only message page
        /// 
        /// 
        private void ReadOnlyPage(ActionExecutingContext filterContext)
        {
            filterContext.Result = new RedirectResult("~/ReadOnlyAccess");
        }


        /// 
        /// Activate javascript to disable all input fields.
        /// 
        private void DisableInputOnForm(ActionExecutingContext filterContext)
        {
            filterContext.Controller.ViewBag.DisableAllInputElements = true;
        }


        /// 
        /// If ForReadOnlyUserAttribute is applied for a method, return that attribute object.
        /// If actionName provided, work with that action in the controller. Otherwise work with currently executed action.
        /// 
        private ForReadOnlyUserAttribute GetForReadOnlyUserAttribute(ActionExecutingContext filterContext, String actionName = null)
        {
            MethodInfo method = GetActionMethod(filterContext, actionName);
            if (method == null) return null;

            var readOnlyAttribute = (ForReadOnlyUserAttribute)Attribute.GetCustomAttribute(method, typeof(ForReadOnlyUserAttribute));

            return readOnlyAttribute;
        }


        /// 
        /// Return MethodInfo for the executed action on the controller.
        /// If actionNameString is provided we return MethodName for the provided name.
        /// If no actionNameString is provided, we return the currently executed Action.
        /// 
        private MethodInfo GetActionMethod(ActionExecutingContext filterContext, String actionNameString = null)
        {
            var controllerType = filterContext.Controller.GetType();

            // get all the parameters from the original request. Copy Types of parameters in an array. 
            var paramTypes = filterContext.ActionParameters
                .Values
                .Where(p => p != null)
                .Select(o => o.GetType())
                .ToArray();

            var actionName = actionNameString ?? filterContext.ActionDescriptor.ActionName;

            // find a method that has exactly the same set of parameters as the request.
            var detailsAction = controllerType.GetMethod(actionName, paramTypes);

            return detailsAction;
        }


        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // 1960: "I have a great idea! lets have every person in the country carry a radio tracking beacon!" 
            //  "That'll never fly!"  
            //
            // 2012: "I can has TWO iphones??"
        }
    }

That class is registered in Global.asax.cs:

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new ReadOnlyFilter());
        }

And you need ForReadOnlyUserAttribute.cs:

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false) ]
    public class ForReadOnlyUserAttribute : Attribute
    {
        public bool DisableInputFields { get; set; }
        public bool AllowPost { get; set; }
    }

And in your global Layout page you need to add following block of code for javascript. Taking you already have jQuery in your project:

    @{  // if we are working with read-only user and Edit page does not have Details alternative, we show Edit page, but with all the controls disabled.
        var disable = (bool?) ViewBag.DisableAllInputElements;  // this is set in ReadOnlyFilter
        if (disable.HasValue && disable.Value == true)
        {
            //script from asawyer: http://stackoverflow.com/a/12477283/809357
            
        }
    }

To disable input forms on the pages, add [ForReadOnlyUser(DisableInputFields = true)] attribute on the controller action:

        [ForReadOnlyUser(DisableInputFields = true)]
        public virtual ViewResult Details(int id)
        {
            var model = _personRepository.Find(id);
            return View(model);
        }

To allow POST actions add [ForReadOnlyUser(AllowPost = true)] to actions where you take POST submit.
Beware – this allows unauthorised users to do POST actions. That was fine in my case, but might not be acceptable for you, so change the filter code a bit.

And that seems to be it.