Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
Experience Sitecore! | All posts by martin

Experience Sitecore!

Martin Miles on Sitecore

Helix project, MVC routing and the form posting back to controller. Part 3 - Adding validation

In previous post we have created an MVC form, that submits to a feature controller and set up the routing to make it all work. In this part we'll add validation to that form. This part does not differ from traditional MVC approach, however let's make our form smooth and complete.

1. Add validation controls into a page for each of inputs:

@using (Html.BeginRouteForm(MvcSettings.SitecoreRouteName, FormMethod.Post))
{
    @Html.LabelFor(x => x.FirstName)
    @Html.TextBoxFor(x => x.FirstName)
    @Html.ValidationMessageFor(x => x.FirstName)

    @Html.LabelFor(x => x.LastName)
    @Html.TextBoxFor(x => x.LastName)
    @Html.ValidationMessageFor(x => x.LastName)

    @Html.LabelFor(x => x.Email)
    @Html.TextBoxFor(x => x.Email)
    @Html.ValidationMessageFor(x => x.Email)









}
2. Model needs to be updated with validation action filter attributes, provided by DataAnnotations:
using System.ComponentModel.DataAnnotations;

namespace YourSolution.Feature.Test.Models
{
    public class TestModel
    {
        [Display(Name = nameof(FirstNameLabel), ResourceType = typeof(TestModel))]
        [Required(ErrorMessageResourceName = nameof(Required), ErrorMessageResourceType = typeof(TestModel))]
        [MinLength(3, ErrorMessageResourceName = nameof(MinimumLength), ErrorMessageResourceType = typeof(TestModel))]
        public string FirstName { get; set; }

        [Display(Name = nameof(LastNameLabel), ResourceType = typeof(TestModel))]
        [Required(ErrorMessageResourceName = nameof(Required), ErrorMessageResourceType = typeof(TestModel))]
        [MinLength(3, ErrorMessageResourceName = nameof(MinimumLength), ErrorMessageResourceType = typeof(TestModel))]
        public string LastName { get; set; }

        [Display(Name = nameof(EmailLabel), ResourceType = typeof(TestModel))]
        [EmailAddress(ErrorMessageResourceName = nameof(InvalidEmailAddress), ErrorMessageResourceType = typeof(TestModel))]
        [Required(ErrorMessageResourceName = nameof(Required), ErrorMessageResourceType = typeof(TestModel))]
        public string Email { get; set; }

        // Labels and validation messages: instead of hardcoded you may take it from Dictionary
        public static string FirstNameLabel => "First name";
        public static string LastNameLabel => "Last name";
        public static string EmailLabel => "E-mail";
        public static string Required => "Please enter a value";
        public static string MinimumLength => "Should be at east 3 characters";
        public static string InvalidEmailAddress => "please enter valid email address";
    }
}
3. Last but not the least, need to decorate POST action with validation action filter attribute, that runs validation prior to executing controller and returns validated view model on failure or runs into controller action if there no errors. So, updated controller action:
        [HttpPost]
        [ValidateModel]
        public ActionResult Test(TestModel loginInfo)
        {
            // do something on successful form submission
            return new RedirectResult("/SuccessfulResultPage");
        }
4. And of course, the ValidateModelAttribute class itself:
using System.Web.Mvc;

namespace YourSolution.Feature.Test.Attributes
{
    public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var viewData = filterContext.Controller.ViewData;

            if (!viewData.ModelState.IsValid)
            {
                filterContext.Result = new ViewResult
                {
                    ViewData = viewData,
                    TempData = filterContext.Controller.TempData
                };
            }
        }
    }
}

5. After running gulp commands for updating views and DLL libraries, an updated page would do validation similar to:


That's it! Finally, our feature project named Test would have the following structure in Solution Explorer:



Thanks for reading!

Helix project, MVC routing and the form posting back to controller. Part 2 - Creating a form

In previous part, we created a test feature, as a part of a Helix-based solution. We also created a page and rendering and wired it together. So, now it's time to create a form.

As a start, let's create a controller, as it is referenced from rendering definition item:

namespace YourSolution.Feature.Test.Controllers
{
    public class TestController : Controller
    {
        public ActionResult Test()
        {
            return View();
        }
    }
}

Then create corresponding Razor view..

@using Sitecore.Mvc.Configuration
@model YourSolution.Feature.Test.Models.TestModel

@using (Html.BeginRouteForm(MvcSettings.SitecoreRouteName, FormMethod.Post))
{
    @Html.LabelFor(x => x.FirstName)
    @Html.TextBoxFor(x => x.FirstName)
    
    @Html.LabelFor(x => x.LastName)
    @Html.TextBoxFor(x => x.LastName)

    @Html.LabelFor(x => x.Email)
    @Html.TextBoxFor(x => x.Email)
}



.. and model that represents our form, to be passed between controller and view:

namespace YourSolution.Feature.Test.Models
{
    public class TestModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
    }
}

As we are working with a project outside of webroot, we need to use gulp in order to copy this view into corresponding folder on the website (or you may copy that manually), same for the feature DLL.

After refreshing browser you will see the view. Obviously, when trying to hit "Submit" button - nothing happens as there's no POST controller action method. So let's add the one:

namespace YourSolution.Feature.Test.Controllers
{
    public class TestController : Controller
    {
        public ActionResult Test()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Test(TestModel loginInfo)
        {
            // do something
        }
    }
}

Still not there... why? Let's troubleshoot that. First thing to do is to find out where form does POST to. In webinspector, it shows:

  <form action="/test" method="post"> ... </form>

So far so good - that looks correct (form POSTs to itself). But how /test URL corresponds to YourSolution.Feature.Test.Controllers.Test() method of YourSolution.Feature.Test feature project?

That's where routing comes into a play. As you know, feature is just a single project that is built into individual DLL and is deployed into /bin folder of project webroot along with other libraries. So how do we wire up /test with that particular method?

We apply config patch Feature.Test.config in order to add a pipeline processor right before the one that initializes MVC routes.






      
    
  

After running gulp configuration task this patch will be put into YourSolution/Website/App_Config/Include/Features folder along with custom configuration include file patches for other feature modules. Corresponding processor will be the following:

using System.Web.Mvc;
using System.Web.Routing;
using Sitecore.Pipelines;

namespace YourSolution.Feature.Test.Pipelines
{
    public class RegisterWebApiRoutes
    {
        public void Process(PipelineArgs args)
        {
            RouteTable.Routes.MapRoute("Feature.Test.Api", "api/test/{action}", new { controller = "Test" });
        }
    }
}

Finally the last bit to make routing work - modify _ViewStart.schtml view file on the project level. Here is it:

@{
    Layout = (this.ViewContext.IsChildAction) || (this.ViewContext.RouteData.Values.ContainsKey("scIsFallThrough") && 
        Convert.ToBoolean(this.ViewContext.RouteData.Values["scIsFallThrough"])) ? null : "~/Views/Shared/_Layout.cshtml";
}

If you have done everything correctly, after gulp'ing your assets into web folder and refreshing the page in browser, you'll see a form similar to the one below:


That's it! Now the form is fully functional and POSTs to a controller, however in order to make things even better - let's apply form validation.

References:

Sitecore Helix Documentation


Helix project, MVC routing and the form posting back to controller. Part 1 - Prerequisites

At the moment I am working on challenging project that is powered by Sitecore 8.2and follows Helix principles.

Last week I implemented a Feature, that has an MVC form posting back to its controller (here I mean native MVC, not Web Forms for Marketers) module. "Not a big deal" - I thought initially... and spent more time that positively expected until finally got it implemented.

The difference between Helix project and more traditional Sitecore MVC application is that in Helix your assets - controllers, views, statics etc. are kept within an individual project for a particular Feature (or Foundation, or Project - depending on what functionality you're implementing).

Prerequisites.

I assume you already have your Helix solution ready (you may use Habitat, as an "instance" of Helix). So let's start with Sitecore.

I create a page called Test under website root using one of page templates. Next, a rendering is required to be assigned into a placeholder on a page. I create a controller rendering named Test and put it under this feature folder (also called Test). Please notice, that I have to specify controller with fully qualified name with a name of assembly where this controller resides.


Tip: do not forget to publish your items, unless you're working in a live mode from Master DB directly.


Next, let's create a project structure in Solution Explorer. As we're building a Feature, create a solution folder under Feature folder in Visual Studio and name it Test (as a feature name). Create a class library project within that folder following Helix naming conventions YourSolution.Feature.Test with the same namespace and assembly name. The easiest probably would be simply to copy project folder from an existing feature and change namespace / types there.


You need to have Web config to the project root. Please ensure you are referencing the same .NET version as set in Target Framework of the project, in my example it is 4.5.2:






  





      



      



      



      



      
    
  




    
  






    
  


Also you need to have web.config within the /Views folder to make IntelliSense work properly





Below is the minimum references you'll need to have. DataAnnotations library is not essential, for sure, but is included because it'll be needed at step 3):



At this stage we're set. Let's mote to the next step - creating and wiring up a MVC form on a rendering.

References:

Sitecore Helix Documentation

Sitecore London User Group Is Back

I am proud to announce that I have managed to find a sponsor for an oncoming Sitecore User Groups in London after a big half a year gap caused by lack of sponsorship.

The event is sponsored by Explore group.Those who have been on the market for a while probably know Matt Lee - he's the one of the best agent dealing with Sitecore opportunities exclusively and always has numerous contract opportunities in his pocket, so if you're planning to find a new contract - it make sense to notify him directly few weeks in advance.

Please join us on Tuesday 29th November from 18:00 at Balls Brothers on Mincing Lane, EC3R 7PP for an evening of networking, learning and of course complimentary food and drink!


Back to blogging after a while

I am back after a certain period of time that I haven't been posting for a while. So what did I do since that time:

  • Completed my 2-years contract for Vitality Health achieving all the deliverables and left them with a team of high lever professionals I was happy to meet, interview and worked with together.
  • In summer time I have undergone a serious operation (with even more serious preparation process), that kept me out on bench (from contracting) for 4+ months so far. Luckily, all went successfully and I have almost recovered.
  • Managed to attend several Sitecore events, such as SUGCON and Symposium, as well as numerous user groups.
  • Concentrated on Sitecore Link project as it is times more important for the community rather than blog posts.
  • Finally picked up a contract at Cannes Lions Festivals in order to work on challenging tuple of Sitecore and Salesforce.

As all the issues are getting sorted, I am going to pay more attention to the blog having a decent technical backlog of topics to write about as well as drafts started but left halfway that still need to be finished and published. However at the moment Sitecore Link takes all of my free time and even more that that (by taking few hours from sleep). That result an impressive progress and even more interesting thing are coming - follow me in Twitter and stay tuned.

Sitecore Habitat

Few times I have been already demonstrated a new modular (I'd say revolutionary) architecture approach to Sitecore - Habitat. So my curiosity won, and I started investigating it. Meanwhile, I decided to share in one place all the useful links about Habitat I've managed to find.

What is Sitecore Habitat

As authors say, Habitat is a Sitecore solution example built on a modular architecture. The architecture and methodology focuses on simplicity, flexibility and extensibility. It will empower you with a consistent and discoverable architecture with ability of adding changes quickly and without worry, extensible with new features without steep learning curve.

Habitat is developed and managed by a team in Sitecore Product Marketing with members all over the world (Australia, UK and Ukraine).There are no plans to incorporate Habitat into the Sitecore product, but it will rather serve as a reference implementation showcasing aspect of Sitecore developing. Sitecore is and will continue to be committed to being an open development platform catering for many architectural and DevOps.

Sitecore encourages technical specialists to take part in Habitat. I was shown it for the first time on Sitecore 8 training in London and was amazed by architecture, how things looked differently to what used to have and logical and well-thought at the same time! So, here are some resources I managed to find and share about this project


References to Sitecore Habitat

Anything missed? Please let me know so that I will update the post.

Sitecore Technical User Group UK - January 2016 - Download presentation

Yesterday I have attended Sitecore Technical User Group in London and would like to share presentations from it. There were 3 presenters, talking about:

1. "CDN with Sitecore" presented by Kamruz Jaman, a Sitecore MVP 2013-2015 and in general one of the most experiences Sitecore architect, who seems to have an answer to any question (StackOverflow). He reviewed know approaches of implementing CDN into a solution in order to reduce bandwidth and improve you servers performance, and demonstrated the most complex - integrating Azure into Sitecore with media items being directly uploaded to the cloud storage,
Download presentation (521.5KB)

2. "Continuous Integration & Delivery for Sitecore" by Jason Bert.
Jason seems to know everything about CI with Sitecore. He stated, that is absolutely doable to achieve a working CI setup with Sitecore, GIT, TeamCity and Octopus Deploy and showed us how-to. Less theory in favor of a practical demo in real-time!
Download presentation (4.4MB)

3. "Sitecore 8.1: new Features and Improvements" presented by Steve McGill.
Steve guided us through serious list of new features and improvements in Sitecore 8.1 - there are so many sweeties I am anticipationg to start working with! At the end of presentation he also discussed Sitecore Habitat - a project bringing modular approach into Sitecore.
Download presentation (2.3MB)

Steve McGill and Kamruz Jaman:


Light of knowledge is coming out of Jason Bert


Thanks to presenters and everyone who has attended!

Final post of the year

Dear friends,

This is my final post for this year, I will be on holiday from today and till the first decade of 2016. I want to say warm thanks to everyone who has supported and inspired me during last year, say thank you for your feedbacks, they were crucial for me to commit and go ahead.

I wish you Merry Christmas and Happy New Year and will stay in touch!


All Sitecore reference - mass links update

All Sitecore References project has just got a mass links update, which includes:

  • All StackOverflow questions to date
  • Blog posts I am watching
  • Reconsideration of existing links in order to achieve precise matching


And just to remind - if you have a blog and want add links from it into All Sitecore References, please use Suggest Links page to do that.


Hope you find this project helpful!



I join "The Monads" team at Sitecore Hackathon 2016! Which team do you?

I am happy to join The Monads team at this highly expected event for all of Sitecore Community on Friday January 29th, will be working together with Richard Seal and Justin L, both from USA. This is my first hackathon ever, so I am excited about the event but at the same time a bit worrying. In any case, will do the most of what I can within these 24 hours.

Are you a Sitecore developer? Why not to join the event, it will cost you nothing (except the tome, for sure) but you can get many valuable insights, meet other Sitecore enthusiasts and result having your own module at the marketplace.

You don't need to find people to create a team - just ask for joining any of existing with two people already, like I did.

To go ahead the hackathon please contact Akshay Sura - he is an organizer and will help you with that.

Best luck to all the teams and have fun!