When I first saw the Dependency Injection pattern used in a source code, I did not understand what I was looking at. For a beginner, it just seemed as an unnecessary complication made be some senior developer, to make my life even harder. Passing some objects into the service just to call their methods. Making a complicated constructor to pass 15 other dependencies. But I was young and some time had to pass before I had the aha moment and finally understood what it is all about. After that, it all made perfect sense. Instead of creating lot of nested code, that is tightly coupled, with static method, you just pass required dependencies into the object. With that, you can create the code in the way that will allow you to focus of writing and testing only one functionality at a time. You can easily mock other dependencies that are not relevant at the moment. It introduces a clarity in the code.
Umbraco and IoC
Umbraco documentation states as following:
We don’t use IoC in the Umbraco source code. This isn’t because we don’t like it or don’t want to use it, it’s because we want you as a developer to be able to use whatever IoC framework that you would like to use without jumping through any hoops. With that said, it means it is possible to implement whatever IoC engine that you’d like!
With that in mind, I would like to show you how to add the Windsor Dependency Injection container into an Umbraco web application as an example.
Adding IoC into Umbraco
First step to add Windsor Container is to create class that extends UmbracoApplication class. This gives as ability to override method OnApplicationStarted. In this method we can replace both default MVC and WebApi Dependency Resolvers.
_lifeTimeScope = new WindsorWebApiDependencyScope( _container, _mvcDependencyResolver, _webApiDependencyResolver); }
public object GetService(Type serviceType) { return _lifeTimeScope.GetService(serviceType); }
public IEnumerable<object> GetServices(Type serviceType) { return _lifeTimeScope.GetServices(serviceType); }
public System.Web.Http.Dependencies.IDependencyScope BeginScope() { return new WindsorWebApiDependencyScope(_container, _mvcDependencyResolver, _webApiDependencyResolver); }
public void Dispose() { } }
Constructor in WindsorDependencyResolver takes three parameters, first is the Windsor container, second one is the default MVC Dependency Resolver and the third is the default WebApi Dependency Resolver. The latter is used to first check if the service is not registered there.
The BeginScope method returns adapter class of Windsor container for WebAPI IDependencyScope. It allows to restrict service lifetime to a scope. It can be useful for situation when you don’t want to create singletons and also you don’t want service to be created every time it is being referenced. For example, we can create a scope for a http request and allow all methods/classes to use same instances during one request.
To register custom services you must call the Register method on the container. The Component class is a static class that serves as a Factory class and allows to connect interface with it’s concrete implementation. Also we need can define the lifetime of the registered class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
publicstatic IWindsorContainer Initialize() { var container = new WindsorContainer();
Project that I’m working on contains a form that is being validated. My latest task was to add remote validation for the password field to check it against existing server code. I’ve described this in my previous post.
There was one problem which I did not described in that post. This site has multiple languages and we are using Umbraco dictionary to manage translations for texts on our page. One of those texts are validation messages for form.
Key to this dictionary item is set via attribute that is marking property.
The MyProject.Form.Password is an entry in Umbraco dictionary that was translated into couple of languages.
It worked great with server side validation. After form was submitted, whole Umbraco page was send to server. Server had full context for a page. Proper culture was correctly set based on the Umbraco page context. So validation message was displayed in proper language.
Problem appeared when I’ve started to use the RemoteAttribute. This way I was calling server validation method with an AJAX request. In this situation, Umbraco could not correctly read the language from the request.
The method I found in the existing solution was to get current culture from the url and mapping in Umbraco.
Following algorithm was used to detect current culture.
///<summary> /// Gets domain object from request. Errors if no domain is found. ///</summary> ///<param name="requestDomain"></param> ///<returns></returns> public IDomain GetMatchedDomain(string requestDomain) { var domainList = _domainService .GetAll(true) .ToList();
// walk backwards on full Request until domain found string currentTest = fullRequest; IDomain matchedDomain = null; while (currentTest.Contains("/")) { matchedDomain = domainList .SingleOrDefault(x => x.DomainName == currentTest.TrimEnd('/')); if (matchedDomain != null) { // this is the actual domain break; } if (currentTest == requestDomain) { // no more to test. break; }
currentTest = currentTest.Substring(0, currentTest.LastIndexOf("/")); matchedDomain = domainList .SingleOrDefault(x => x.DomainName == currentTest); if (matchedDomain != null) { // this is the actual domain break; } }
return matchedDomain; } }
To test it I’ve created the view. When the page is viewed in English language, both fields display message in English language. But when I switch to Polish language demo.umbraco.com/pl, then first message is displayed in English and the second one in Polish.
I hope that helped you. :)
You can find working version of this code in my github repo.
My task was to add client side validation of password field to existing form. Validation on server side was already implemented. Rewriting the password validation algorithm on client doesn’t made sense. Only question was how to reuse this logic.
I’ve used the jQuery Unobtrusive Validation library provided for ASP.NET MVC. MVC comes with System.Web.Mvc.RemoteAttribute class. This class needs to be put on property that you want to remotely validate.
public class MemberRegisterModel : RenderModel, IValidatableObject { public MemberRegisterModel() : base(UmbracoContext.Current.PublishedContentRequest.PublishedContent) { }
[DisplayName("First Name")] public virtual string GivenNames { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { throw new System.NotImplementedException(); } }
Solution
The RequiredAttribute is telling the validator that this property is required. We could use that information to automatically render the required indicator -> *.
To check if property should be marked with * we need to check if the propert has the RequiredAttribute. Below code checks if given property has a attribute of type.
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.