1 2 3 4 5 6 7 8 9 10 11 12

MVC postback for users without JavaScript - Post 2

21/06/2015

Posts in this series:

So far we have created a form which performs a postback to the server to add more input fields to the same page. We have encountered an issue with MVC seeming to cache partial views (or at least the values inside them).

Step 4

Step 4 attempts to fix the caching of the selected value field.

I spent hours looking for a way to stop MVC caching partial views, which is what I thought was happening. I tried disabling the output cache and loading the partial views via actions, neither of which helped. I finally found this answer on StackOverflow; the ModelState holds the old values when a view is reloaded via an HTTP POST even if you change the values of the model in the action.

By removing the specific value from the ModelState the value clears properly and the view displays as expected.

private ActionResult AddPostback(OrderViewModel model)
{
    ModelState.Remove("SelectedMenuItem");
    model.SelectedMenuItem = null;

    return View("Order", model);
}

The form now works as expected, the "add another" button adds another input to the page by reloading the page, the submit button still submits the form to the server and redirects to the summary screen. Now we have the screen working for users without JavaScript however users get a "screen flicker" due to reloading the page when clicking "Add another".

See this image for an example of the screen flicker non-JavaScript users will see, this seems like an acceptable compromise, since there's no way to prevent the page having to reload for these users. However for people with JavaScript enabled it would be nice to offer a cleaner user experience.

...

MVC postback for users without JavaScript - Post 1

20/06/2015

Posts in this series:

Despite only around 1.2% of users having JavaScript disabled there is still a requirement to develop sites which work for users who have JavaScript turned off, especially sites which provide government services. The UK's Government Digital Services (GDS) require that a site works without JavaScript and is then enhanced using JavaScript. This causes all sorts of problems designing forms, especially where there is an "Add more" option for input fields.

Designing something like an "Add more" functionality with JavaScript is fairly trivial, having it work for those without is less so. Having encountered this problem several times I've written a summary of the approach I have used to address this.

The code

All the code for this tutorial is available on GitHub. I have used Git's branches to take snapshots of development changes. The final code is in the branch "step-5". Additonally I have hosted the website on Azure so you can see what the final page does here.

The product

We are designing a page to allow users to choose items from a menu, once they have selected as many items as they want, they submit the form and are taken to a summary of their active orders:

The screen features dropdowns containing menu items and an add another button allowing the user to add more input dropdowns

...

Core CLR and System.Xml

09/06/2015

If you need to use some package which is dependent on System.Xml with Core CLR / DNX Core you simply add the Nuget package System.Xml.XmlDocument rather than referencing the GAC System.Xml.

This allows you to keep your code in Core CLR friendly mode.

System.Xml.XmlDocument on NuGet

...

Visual Studio 2015 and Gulp

03/06/2015

Having played around with the Visual Studio 2015 preview a bit I've tried to learn how Gulp integrates with the Web Application project.

Gulp seems like one of those many, many, constantly appearing JavaScript libraries with names like YamahaPotplantSaucepan.js which are impossible to keep up with. However since it takes the place of the Bundle config it's important to be able to achieve a basic level of familiarity with it.

What does it do?

Gulp describes itself as a "streaming build system" which basically means you can wire up a pipeline of operations to perform on your content, such as JavaScript and CSS.

By default the project template comes with a gulpfile (shown in the image as #1). This is configured to take the dependencies from Bower (which is a package manager loading a few jQuery packages in by default) and copy them to the wwwroot/lib folder (#3 in the image).

1 is gulpfile.js, 2 is package.json, 3 is wwwroot folder, 4 is dependencies folder

...

SpecFlow looking for When instead of Given step

20/05/2015

When writing some automation tests using Selenium with SpecFlow recently I was faced with an odd error:

    No matching step definition found for the step. Use the following code to create one:
    [When(@"I add a new dog")]
    public void WhenIAddANewDog()
    {
        ScenarioContext.Current.Pending();
    }

The suggested code was using a [When("My Scenario")] step despite the feature file declaring it as a Given:

Scenario: Check for existing dog
    Given I have a new Dog Controller
    And I add a new dog
    When I check if the added dog exists
    Then The check is true

(This feature is written badly to illustrate the error).

The step it couldn't find was the And I add a new dog step. Despite showing as bound in the feature file and being able to navigate to the step definition, the running test couldn't find it and was looking for a When instead of a Given.

This is because the previous step was calling sub steps as follows:

public class DogControllerSteps : Steps
{
    [Given("I have a new Dog Controller")]
    public void CreateDogController()
    {
        Given("I have a new query bus");

        When("I create a new dog controller");
    }
}

Inheriting from Steps allows us to reuse step definitions from the same or other step files.

When SpecFlow runs this it knows that it last ran a When step, despite being in the definition of a Given. Therefore when the next step is defined with And, it looks for a When. To fix this you can simply change your feature to be more specific:

Scenario: Check for existing dog
    Given I have a new Dog Controller
    Given I add a new dog
    When I check if the added dog exists
    Then The check is true

Passing tests :)

...
1 2 3 4 5 6 7 8 9 10 11 12