Remake of cascading dropdowns with KnockoutJS: Part 2 – cascading behavior

This post is second part of series started here.

Starting point is this changeset on GitHub.

If you don’t want to go through all these steps manually, you can download finished code sample produced in this post from this changeset on GitHub and fiddle with it while reading this post.

In previous post, I created custom Knockout binding, named remoteOptions that accepts url of http service as parameter and loads options from that service instead from view model. That can help to reduce amount of code responsible to build reference data that needs to be available to user to choose from, as with this binding you have one piece of ~10 lines of code for all dropdowns that always have same content. This does not get me very far, as, at least on projects where I worked on, most of the dropdowns were dependent on something, i.e. some attribute of currently viewed set of information, or some other information that user already entered in current form (i.e. when user chooses Female gender, you might want to remove Mr. from title dropdown etc).

Just for reference, I’m adding current state of custom binding, where I left it on GitHub:

Screenshot 2014-05-13-20-26-59-4598210

As there are two dropdowns (category and subcategory), I want to make second one depend on first (load it when user chooses value in first based on that value). For that, I will change binding so that it tells what parameters I want to pass to my service on configured url:

Screenshot 2014-05-13-22-30-59-3084533

I want to pass id of selected category to my service as parameter named ‘category’ and I want to tell that to my binding with parameters:{ category: categoryId }. Now, I have to make sure that my view model has this categoryId defined and pointing to Id of category:

Screenshot 2014-05-13-23-43-46-7844669

Note that this view model is just an JavaScript object made on the fly for this demo, if you are working on a big application that may have large (or even composite) view models, maybe with inheritance, please read this great article about prototypes in JavaScript which will help you better understand how to use new keyword in JavaScript and properly build your models.

Back to cascading dropdowns, now I have Id value of currently selected category in categoryId property (computed, so that it will automatically update after every change in first dropdown). If I go now to my binding and inspect its value when it is processing this dropdown by setting breakpoint after binding is assigned from valueAccessor() (if you set breakpoint, let it execute first time when is processing first dropdown), I see that I have category here as observable:

Screenshot 2014-05-13-22-38-09-0020760

dependentObservable is function name that is remnant of pre-2.0 version of Knockout, and now is same as computedObservable.

To make my subcategory options dependent on category, I will create subscription that is refreshed when any of parameters is refreshed, and then use it to reload data from server when that happens by subscribing refreshOptions function to it in init binding handler:

Screenshot 2014-05-14-23-25-59-1980099

The catch here is in when any of parameters is refreshed, as parameters are passed from binding as names of properties on view model, and binding contains references to their observables. That means that parametersChangeListener computed observable will automatically get new value and notify its subscribers whenever user causes change to any of subscribed observables (in this case categoryId which is indirectly updated by changing selection in category dropdown).

Return value of parametersChangeListener will always be plain JSON object, because every of observables is read with ko.unwrap, which will also support any non-observable variables without problems. That makes it suitable for direct pass to getJSON (you might want to use post here instead, for example to prevent caching response, or to have your http endpoint better secured).

If I try to run it now, I can see that subcategories are filtered based on selected category:

Screenshot 2014-05-14 23.37.33 Screenshot 2014-05-14 23.37.40

Best of all is that this subscription is generated automatically, from whatever is configured in binding, and you can have as many linked dropdowns as you want, they refresh automatically and track changes on their parents.

Every time when I change category, binding makes new ajax request and loads corresponding items for dependent dropdown:

Screenshot 2014-05-14-23-35-38-0394038

Screenshot 2014-05-14-23-35-47-3420418

So, there is cascading part of behavior. Source code is here.

I’m a little busy right now with search for new apartment and relocation, but I will try to continue this series and further improve what we have here.

Till next time!

 

 

Remake of cascading dropdowns with KnockoutJS: Part 1 – creation of custom bindings

One of all-time most popular articles on this blog is AJAX  Cascading Dropdown (actually whole series), which still receives lot of attention even after 3 years.

Not surprising, as this is universal problem that is always present, and any business has some kinds of categories and groups of its own, with more or less levels deep.

Small aside to prevent wasting your time: if you are advanced KnockoutJS user, then you might want to wait for next article of this series, where I will be improving binding from this one to add cascading interactions. This post is more detailed and suited for developers who had only used default bindings that come with KnockoutJS, without many customization.

As browsers advanced, and got closer and closer to a common standard, jQuery became less and less necessary, and other frameworks emerged to address problems of a mess that very often gets produced when many developers try to produce “rich client” UI with jQuery. Hard-coded ids, storing variables in hidden fields to communicate between client and server (and even to communicate between different JavaScript “modules” when there is no real modularity and dependency injection), global functions and variables that are shared between in-line JavaScript and referenced files… you name it. Don’t get me wrong, I am aware that it IS possible to produce something clean and maintainable using jQuery and its plugins, and if you happen to be one of these people who knows how to do it, just think about how easy is to find team of developers who know the same? And even if only benefit of MVVM and data-binding frameworks would be avoiding of copy-pasting selectors all over the place and removing hidden fields, it would be worth learning them, so it is not surprise that they are now so popular for client-side development in JavaScript.

So, these two facts, popularity of my first post about jQuery version of cascading dropdowns, and popularity of Knockout are obviously good clue for me that people are solving same problem today with Knockout, and this is why I decided to create new, updated version of my initial blog post, this time with KnockoutJS. For any of you asking why KnockoutJS and not some other library, my answer is that is first data-binding library I learned couple years back, and even if it is not my favorite anymore, I still like it, it is being used on most of projects I work on, and I believe it won’t go away just yet, so with many people using it and continuing to use it in future, I believe that this article will provide quality content for my readers. And, besides that, I’ll make AngularJS version next :).

So, goal of this series of articles is to implement support for series of dropdowns that are depending on each other (choices avalable in some of them depend in chosen values in others), with items being loaded from remote service, and dependencies between them being managed automatically. All of that should be simple to use and reusable, meaning that no new code needs to be written when you use it 5, 10 or 50 times. To make that work, I will create custom binding. If you never created custom binding, I hope that this article will give you all necessary guidance to be able to create other bindings, depending on your needs.

In this, first article, I’m going to make step-by-step guide on how to implement part of this feature as custom knockout binding, which loads items from server, but without cascading behavior (so multiple dropdowns, no interactions between them), and at the end you have link to source code if you just want to quickly add this binding to your project and (hopefully) solve at least one of your problems. By reading it, you will also find out about my approach to creation of custom bindings.  I derived it after years of experience in creating them, and I believe it is good, as it allows you to add one small tweak at a time, and you always know if a line you added breaks something. Obviously, there are always areas to improve, and if you have some tips, feel free to share them in comments. Custom bindings tend to be pieces of code you don’t write every day, so you usually forget how they work, and what are arguments for handlers. Therefore, taking this iterative approach is what I usually do when I see that I need new binding, if I haven’t created one yesterday (so that I remember all this stuff and can skip baby steps).

If you don’t want to go through all these steps manually, you can download finished code sample produced in this post from this changeset on GitHub and fiddle with it while reading this post.

To reduce overhead for getting some base to work on, I will use ASP.NET MVC5 with Bootstrap 3.1.1 LESS template for Visual Studio. This template gives you already working application with decent css where I can start implementing this (almost) immediately. Only missing prerequisites that I need to add are knockout and ko lite tools:

PM> Install-Package knockoutjs
PM> Install-Package KoLite

To start with, I’m cleaning up index page, adding reference to knockout and activity plug-in from ko lite tools (that we don’t need yet, but when options are loaded with ajax, some form of feedback for user will be necessary), and creating one select to bind with some options:

Screenshot 2014-05-11-16-37-33-8117064

If you didn’t know, you can hardcode your data when using knockoutjs bindings, and model is here just because I plan to use it, but this already produces dropdown with two options, second being selected:

Screenshot 2014-05-11 16.38.13

Now, on to create custom binding. As I want to display some options, that will be loaded using ajax, good place to start is default ‘options’ binding that comes with knockout. For start, you can create your alias for it (pass through call to options binding without changing/adding anything), and then run application to make sure all still works as before. So, I created ‘remoteOptions’ binding and used it instead of ‘options’ to check if all works as expected:

Screenshot 2014-05-11-16-43-54-4084819

If you don’t know how bindings in Knockout work, here is very short explanation for arguments that are passed to your handler:

  • element is DOM element of page that contains data-bind attribute for your binding,
  • valueAccessor is function that returns object assigned to your binding in data-bind attribute,
  • allBindings is an object that contains all parsed bindings from data-bind attribute.
  • bindingContext an object that contains and $data property that represents your current model (i.e. model that you used in applyBindings, or current item in foreach binding, or property that was used in with binding), but also $parent, $parents and $root properties where you can access other parts of your model (traverse up from current node)

For more details, read documentation.

So, my goal is to tell my binding where to load options from and avoid having either options or remote address in my view model. That reduces number of properties and lists in view model, and in many cases has effect of making view model much more like (data) model reducing mapping complexity, or removing mapping completely. So, having that in mind, first step will be to change binding syntax (I also changed html and added some css but that is just markup, important part is in red):

Screenshot 2014-05-11-20-40-36-5560672

This now passes an object instead of array of options, and to avoid ko options binding being broken with it, I’m changing my custom binding, just a little bit:

Screenshot 2014-05-11-20-37-08-8765880

As you can see, I’m reading new binding by calling valueAccessor() and at the moment doing nothing except logging its content to console to show you what is in:

{“url”:”categories/get”}

At same time, I created function optionsValueAccessor (actually just moved hard-coded options here) to provide some options that default binding will read and use to display options in select element:

Screenshot 2014-05-11-20-44-44-3633127

I added another option now, and it can be seen in page:

Screenshot 2014-05-11 20.45.42

 

Ok, that part seems to be simple enough, now to get some real options using ajax. For that, I’m exposing very simple http service in web app to return contents of an enum (in real app you would probably read that from some kind of persistence service):

Screenshot 2014-05-11-21-18-35-2731914

So, I want to load list from this http service automatically as options in Category dropdown when page is loaded (and binding initialized), and to accomplish that, I want to have minimal amount of coding configuration, and that would be address of endpoint that contains options for dropdown:

remoteOptions:{ url:’/categories/get’ }

That is rather easy to accomplish with knockout, as we can pass reference to an observable array to underlying default options binding which will show options from that observable array, and set its items once ajax request has been completed. Single problem is that we have to make that ajax call in init method of bindingHandler, as they need to be loaded only once, update is triggered every time user selects item from dropdown, and every time update is triggered, we need to pass same observable array to underlying options binding (no need to refresh all items when selecting one of them). I noticed that passing reference from init to update handlers is not simple, as you can’t write to allBindings (well, you can, but it doesn’t get persisted anywhere, next time when update is called, you get new object without your changes), and you cannot write to value of your property in model, as it is supposed to hold value user has selected (having something else defeats purpose of this blog post). Fortunately, value binds to observable, which is a function, and in JavaScript everything is object (including function), so we can simply add a property to that object (observable, function) that will hold reference to observable array with options:

Screenshot 2014-05-11-21-46-16-5793210

To reduce probability of interference with something else that may be in observable function/object, I tried to give unique name to my property: ‘__remoteDropdown_options’ (if I used something like ‘options’ here, somebody else might used same property name for something else and then if both bindings are used at same time they would read/write different thing in/from same place, and there might be very weird and hard to track down bugs). As you can see, I’m setting it to observable array in init, and firing off an ajax request to load options from url passed in binding. Reference to that same options observable array is returned as result of optionsValueAccessor in update function that initializes dropdown. When ajax request completes, options is filled with result from server, and voila, my dropdown contains these values:

Screenshot 2014-05-11 21.52.44

 

That is kinda cool (especially because with these 10 lines of code you can fill in any dropdown with ajax), but, there is still no trace of “cascading” from title of this post. And, not to mention that in most cases description shown in dropdown will differ from value (i.e. you will have item’s primary key as value, and description as text shown to user). So, let’s add that before trying to add cascading behavior (because that is short and easy, and this post already becomes very long, too long for binding of 10 lines).

First, instead of list of strings, return list of objects that have Id and Text:

Screenshot 2014-05-11-22-09-16-8232341

That makes controller now return array like this:

Screenshot 2014-05-11-22-10-32-2292066

But dropdown now shows three [object Object] items instead of text. Fortunately, we are passing through allBindings untouched to knockout’s default options binding, which already has support for this (read documentation for details). To use this feature, I just need to tell knockout what is name of my text property: optionsText:’Text’. Now is right time to add category as property on my view model to be able to show what is selected:

And yes, that is view model. I know that some of you are going to have hard time to accept that I did not define view model in C#, but it is intentional, not only for this sample, it can be avoided completely. You have view model here, and I believe one is enough. Keep it simple. You don’t need it even when you are accepting your domain entity in controller (when you are saving it), you can define model binder to initialize everything that you need, effectively avoiding one layer of view model classes and mappers (mapper does the same your model binder would do, but you need to add code to call it into your controller, and why do that when MVC already has extensibility point for that?) This is a topic for separate post (still in drafts folder), but feel free to comment about it here.

So, with this here, I’m changing markup to reflect latest change in options that are returned from server, and with having observable to store category in view model, I’m going to show it on screen:

Screenshot 2014-05-11-22-24-44-7241307

 

As you can see, when using remoteOptions, you can use optionsText as with default options binding to choose property to display in dropdown, and value (selected item from dropdown) is bound to category.

As I did not set optionsValue, knockout will set whole object (with both Id and Text) into category observable, and you can see that from with binding and results below:

Screenshot 2014-05-11-22-59-06-0916130Screenshot 2014-05-11-22-59-11-0249004Screenshot 2014-05-11-22-59-16-2570130

These are 3 screenshots of same dropdown with different option selected, as you see, it automatically shows chosen category below.

 

So, to conclude this first part, I’m going to add another dropdown, with subcategories (that should be filtered by category selected in first dropdown, but not yet). For that I need another http service to get data from, and another html markup for dropdown:

Screenshot 2014-05-12-11-37-26-4778034 Screenshot 2014-05-12-11-37-11-4936759

 

So, for this dropdown, different label, different url, and different property in vew model (I have added subcategory: ko.observable()). That produces:

Screenshot 2014-05-12 11.37.35  Screenshot 2014-05-12-11-36-51-8104404

 

With this, I’m ending this post, and source code changeset on GitHub is exactly the place where I’m starting next post, in which I will add dependencies between these dropdowns and filter items in “children” based on selected items in “parents”.

P.S. One of additional purposes of this article is also to document/explain feature that I implemented on my latest project, binding which works on same principles as this, and anyone having trouble understanding it can come here for help. Even if I’m sad that my code requires additional explanation, it is still a good way to celebrate successful migration to new domain for my blog.

Conveniences of using LastPass

This post is intended for few of my friends, to whom I promised to explain how to save time and make their life better and information more secure at the same time.

Some of you saw me when I was logging in to LastPass with YubiKey and I promised to give detailed explanation.

In few words, LastPass is service that enables you to keep all your passwords, credit cards information, notes etc securely encrypted, and you access all of that information using single password (Last Pass that you will have to remember). It comes with plugins for most browsers, which automatically fills your login information when and where you need it. It also had password generator which can generate passwords of given complexity on key-press (shortcut is Alt+G):

Screenshot 2014-04-30-22-01-43-3304169

That means that you don’t have to use one password for multiple web sites, and if one of them gets hacked, others are still secure because they had different passwords.

To install LastPass, just go to their site and download it, you will have to register there with your email and Last Pass, and then when you download it wizard will ask you to import your passwords from your current browser.

 

Second great thing about Last Pass is their mobile app, which enables you to have your secure passwords on your mobile smart phone (smartphones are not really mobile anymore, until I got spare battery for mine, I was constantly connected to some power source). It has integrated browser that you can use for opening web sites combined with password management, but real deal is Last Pass Premium (1$/month), which then uses one of more recent features on Android – draw UI over other apps, and with that offers to fill password in Chrome and other browsers for Android, in your e-banking app, in your social network apps, everywhere. You can associate sites to apps in Android, and when you tap password field it automatically shows dialog to fill login information, or if it cannot find input fields, then you have option to copy username and password and paste into fields. I cannot give you screenshots of these as my phone says that it cannot capture them, because they are “DRM protected images”.

Third part of this post is YubiKey. It is hardware dongle that your computer sees as USB keyboard. It generates one-time password (every time different) that enables same security like token generator for e-banking. When you configure LastPass to use YubiKey, it will ask you for token every time you sign into a new browser (or every time if you don’t tick “trust this computer”). Advantage of using YubiKey is that makes your LastPass account much more secure, as it requires 2-factor authentication: something that you know (password), and something that you have (yubi key). In case that you are accessing your LastPass vault from computer that has i.e. keylogger, someone might get a hold of your password, but YubiKey code is unique, and it cannot be used more than once, so it cannot access your account without it.

However, YubiKey is not only way to give additional security to your LastPass account:
Screenshot 2014-04-30-22-44-52-9146121

Instead of YubiKey, you can use Google Authenticator or some other 2-factor authentication option, but reason why I especially like Yubi is that it is very high quality device (virtually indestructible) and you can have 5 of them associated with your LastPass, so that when you loose one, you can just disassociate it from LastPass. Bear in mind that Yubi is only usable in combination with LastPass Premium.

It is also possible to copy YubiKey seed from one key to another so that they are exchangeable (two keys act as one), but that is something risky unless you keep one in a secure safe and need it only to access something in case you loose first one. But, as soon you loose one, whatever it protects is compromised, and this makes sense only for special scenarios. In my opinion it is better to have different keys associated with one LastPass, as it supports it, and you can disable it as soon as you loose it. Loosing one of two identical generators can sometimes happen without you knowing about it.

Anyway, now that you know about it, first step is to get LastPass. Try it. If you like it, then you can decide if you want Yubi. Standard version comes with one slot configured for Yubi auth, and second empty. For same price (25$) you can also get YubiKey VIP, it gets with preconfigured Symantec VIP authenticator that you can associate to PayPal etc, to log in without LastPass. In second slot you get standard Yubi auth, and only downside is that when you want to use it is that you need press token few seconds longer.

As an added bonus, for any of your sites, credit cards etc. that you keep in LastPass vault, you can share with another user! This is much better way to exchange credit card information than to send it through email (or any other standard communication channel).

Disclaimer: I use affiliate links. If you register for Last Pass through links in this blog, both you and me get month of LastPass Premium for free!

Samsung ATIV Book 8 NP880Z5E-X01 (subjective owner’s) review

I have bought this computer some 6 months ago.

Samsung ATIV 8 on Amazon

It is my primary computer since, as I moved to Germany last year, and did not bring any computers with me, and as I did not permanently settle here, I did not want to buy any desktops until I decide where I’m going to live more than a year. I wanted something lightweight and small, but still with full HD screen, and if possible with decent VGA card, as I was collecting some games that I like on Steam, with plan to play sometimes, so it was nice to have feature.

My primary use of computer is Visual Studio (with Resharper), Office (365 installed offline), reading articles and Skype/Viber. I also run virtual machines in VmWare player or VirtualBox when I want to test something etc. Therefore I wanted computer with i7 CPU. Ram was to be 16GB as it is max that current generation of motherboards can support, and SSD drive as mechanical hard drive is slow (biggest bottleneck of any computer), heavy, and unnatural for an electronic device. I also wanted good keyboard, but I could not find computer which has it combined with all other qualities, so I decided to buy Das Keyboard Model S Ultimate later.

If you take a look at this computer, it is not really what I wanted, as it has 1TB mechanical, 5400RPM drive and 8GB of RAM. As everything else was acceptable, and it has decent Radeon 8000 series graphics card, I decided I can live with less than perfect keyboard (from what reviews said) and bought it.

First downside, HDD was fixed with Samsung 840 Pro 256GB, which was easy to install, and original HDD is now in this External 2.5″ HDD enclosure, which is very good and I can only recommend it, it even has special connector (not standard mini-USB, but with double contacts, for better power supply). To install HDD into this computer, whole bottom cover needs to be removed, and also you need to disconnect quite a few connectors inside to access HDD, but it should not be a problem for anyone who ever opened a tablet or phone. To find out how to do it yourself, you can see this video on YouTube.

Second downside was trivial to solve, as laptop is delivered with one soldered (you cannot replace it) 8GB RAM module, and I just ordered Kingston 8GB DDR3 1600MHz and plugged it in (there is small cover for installing RAM, so you don’t have to open whole computer).

As I’m not trying to give an complete and objective review on this device (there are already plenty on the Internet), I want to go straight to the point that interests any of you thinking about buying it – what are “hidden” downsides and problems of this device, that you cannot really read from reviews, but you have to use it extensively to find out:

  1. Touch screen functionality enabling/disabling requires you to log out, and if you just close screen lid while computer is on and unlocked, touch is not disabled while screen is off, metal surface interacts with screen (random touch/click/drag events) and can cause all kind of weird things happening on your desktop (from my experience, worse than letting 2-year old play with touch screen). This is one of most annoying issues, that Samsung could solve by providing bug fix for their driver software.
  2. Hard drive is slow, not anything specially slower than other mechanical drives (even faster), but still, in my opinion computer is completely unusable with default hard drive, and if you plan to spend money on this computer, calculate additional cost of SSD with, or otherwise go for similarly priced computer that already has SSD. You don’t need Core i7 in same computer that only has spinning platters storage inside. With SSD, it is completely different device, especially with this Samsung 840 Pro, as Samsung Magician software has “Rapid mode” that uses system RAM for caching, so in normal usage achieves results that are impossible through SATA 3 interface:

    Crystal disk mark of Samsung SSD pro 256GB
    Crystal disk mark of Samsung SSD pro 256GB
  3. If you put it to sleep, while you have “Hybrid sleep” enabled, and configured options to go to hibernation after certain time in sleep (i.e. 2 hours), when moment to go to hibernation comes, computer turns on, and stops on screen saying it cannot load windows. There were very weird things happening with it, i.e. sometimes I would put it to sleep in evening, and when I turn it on in the morning it would freeze on windows welcome. Then I would kill it with holding 4 seconds power switch, do a clean boot, and then just send it to hibernation and turn on again to get my session from last night! I know it sounds crazy, but I did it more than once. Something is wrong with either computer or how windows saves memory to drive, and then it remains for next session. Sometimes this would cause computer to turn on to go to hibernation, and then as I’m not there it would stay so on “cannot load windows screen” few hours, and it would become very hot. It happened in bag once, and if I did not remove it it could have been roasted. If you leave it to sleep in evening with charger disconnected, you may encounter in morning that it is off and battery completely drained, with your windows session gone. I’m not sure if it is caused by installing SSD and enabling Rapid mode, or maybe with installing another RAM module, but I don’t remember having this issue when computer was completely new, but it might have never been configured to go to hibernation after some sleep at that time. For me, issue is solved by disabling sleep, I configured it to always go to hibernation. As SSD is very fast, difference is unnoticeable, so it is very good workaround that completely eliminates issue.
  4. SD card slot is “reduced size” (half depth), so if you are used to carry around a fast and big SD-card to extend your HDD capacity like me, then count it out on this computer, as half of the card sticks out of computer
  5. If you require robust device, but also care that your computer is not scratched, you will be disappointed with Samsung’s decision to put plastic on top of the screen, as it is one of most sensitive areas when computer is in messenger bag:
  6.  Bottom cover is plastic, it will get scratched, change color, and deformed on places which run hot on the inside:

 

So, these are all problems that I experienced with this machine so far. I’m very happy with it, and only first one is annoying, as I forget about it sometimes and close unlocked windows. It is very good device otherwise, I spilled water on it once, keyboard is very good and does not let it inside, and battery is really good, you can work on it 4-5 hours without power.

If you already own it, I can recommend this TeckNet® 90W power supply, which has compatible connector, it is lighter and better looking than original one:

 

If you are still indecisive, feel free to send your questions in comments.

 

Nancy on OWIN – bundling and minification

Continuing with changeset from last time.

I want to introduce bundling and minification without dependency on System.Web (it would defeat purpose of trying to create site on OWIN).

For that, I’m using SquishIt:

Install-Package SquishIt

I found some resources how to use it in Asp.Net Mvc and there is also integration manual on Nancy documentation, none of them is covering case when Nancy is running outside of IIS (and without Razor engine, which I don’t believe it is necessary for this simple example, I might want to add it if I see that I need it, but I want to try to go without it), but they are good samples to see how to use SquishIt API. For bundling, I need bootstraper, which is equivalent of Global.asax.cs in Asp.Net application, and as I want to do minimal customizations, I will use default bootstrapper as base for mine:

 

I’m taking care of bundling itself in separate class, BundleConfig, as Bootstapper is place where all of initialization is performed, and if all that stuff is inside it will become very dirty and cluttered in notime:

Bundle config

I’m separating JavaScript and Css bundling, and within JavaScript, creating one bundle for all libs (and only angular is in it), and another for my “app” where I put whatever js is in app folder.

To keep things simple, and continue using html view, which can only replace tokens from passed view model, I’m going to reference these bundles and pass them to view from my HomeModule:

Bundles added to viewmodel

That produces already complete html tags, so that I can only write them directly in view:

Result:

As a side note, take a good look on contents of this file. You can see that WelcomeCtrl was minified, and minifier used (MsMinifier) did shortening of controller dependencies (which was just ‘$scope’ in this case). Take care when writing applications in Angular to explicitly identify dependencies (by defining modules in array, with dependency names as strings first, then your module as last element of array, like here, “$scope” is a string, and minification does not change it). That allows Angular’s injector service to identify your dependencies and inject them even when minifier performs obfuscation of argument names to reduce amount of characters used.

SquishIt works by taking all of files added to bundle, and packing them together into another file,  that will have given name. If you want to leverage browser caching, then you need to add “#” to file name, and it will be replaced with a “token”, that looked to me as hash at first, but I figured that it must be just a random guid, as it did recreate scripts combined js file without changing any of contents, so it just creates a file with random guid in name and remembers it under given name for lifecycle of application instance.

That is very simple approach, as then all that need to be done is render include tag that references that file name as source, and when something is changed, new file name and url will be created, so no outdated files will be used, and no browser cache will cause problems. It seems very simple and effective, but don’t do it like this! This is just a step to learn how it works, and while it seems fine, it is not the simplest thing that could possibly work. It will create new file every time application is restarted, and if you are hosting your application, you may not be able to control app pool life cycle, which may have rather conservative life policy. If your application works good and you don’t have to check on it, it may generate hundreds of hundreds of these minified files. Another, even more dangerous problem is that I placed my minified scripts file into same directory with other files, while at same time including whole that directory into bundle! That means every time when app pool is recycled, new bundle will be created with all files, and previous bundle(s), effectively doubling size of app folder on every start of application. This exponential progression can go undetected while doing test run of application, because angular tends to be pretty resilient, and even if you redefined some modules few times, it will work, but after couple dozens of restarts, size of served JavaScript can grow to megabytes, effectively killing browser, and eating your outgoing bandwidth on server. And taking your hard drive space. All of that can be pretty expensive. You understand now why I wrote don’t do it in red, it is very dangerous to use it, even if you put your minified file into another folder, you can forget, or someone else who needs to change something will see how bundles are defined and put it there not knowing how it works, or your hosting provider might decide to migrate your web site to new server and reset permissions in process, so you end up with:

What is another reason to avoid it, is that while compilation debug=”true” is set in web.config, SquishIt works same as standard bundling from Microsoft.Optimization, and will not do any minification, it will serve resources unchanged, as in manual version from start of this post, with only difference being that you don’t have to manually include every file from app folder. That makes developer life much easier, but if you don’t deliver version every day (it is as easy as defining publish profile and configuring server for web publishing, and publish in release mode), it will hide this problem until very late in development life cycle. You may figure out something is wrong if you disable debug and then re-enable when you see minified version being picked up too:

 

So, I hope that by now I convinced every single reader that read to this point, that this approach should not be used for serious application. Ever. This can be avoided by using caching of minified resources in memory. It is faster, doesn’t cause hit to hard drive on every request, it does not require write permissions for application pool account, and does not leave any files behind that must be cleaned up. There is already example in Nancy doc, under Advanced – Diskless Caching.

Based on that example, I created my BundlesModule:

This module is working from /bundles subpath, and also uses GZip to compress outgoing stream, and adds etag and Cache-Control headers to leverage browser caching. In debug mode I intentionally reduced caching to 45 seconds, so even if you create bundle with .ForceRelease to enable minification in debug mode, it won’t be cached for long as you will probably be changing files.

To be able to use dynamic parameters type, I had to add reference to Microsoft.CSharp.

As name of bundle is now passed as part of url ({name} part after /bundles/js/), creation of bundles must be changed accordingly, as they were created with different names:

 

Bundle name is now encoded into url in place where BundleModule expects {name} parameter, so rendered url will point back to that module, and pass bundle name that needs to be served:

Screenshot 2014-04-17-00-28-24-4817544

 

There is no more writing to disk, no need for permissions, and we have bundling solution that is as effective as one from Asp.Net Mvc.

Source code is at github, as usual. From here there are many things that need to be done to make one application, and I still have not decided what to do first. If you have suggestions, please leave a comment. Thanks!

 

 

Nancy on OWIN – serving static resources

For this post, I’m using same playwithowing project I created during last blog post, which is on github.

First thing that I want to do, is add some NuGets:

PM> Install-Package bootstrap
PM> Install-Package angularjs

These two are enough for now, I have both css and javascript files that I need on client now.

To use them in view, next step in Asp.Net would be to drag&drop them into view, css in <head> and scripts to bottom of <body>. VS produces proper tags for them:

 

If you run application now, you can see that all already works, everything loads just fine:

 

That is very nice, as by default OWIN doesn’t serve static resources (you must configure simple FileServer, which you can do anyway if you want to enable file browsing in some of your folders, but then add builder.UseNancy() line at end of Configure method, as Nancy handler is greedy and it will handle request before it gets to file server). But even without it, this works because of default conventions in Nancy, which are summed in first sentence on that page: stick stuff in /Content .. done.

 

As a side note, notice that everything is loaded within 200ms,
which is nice, especially when having in mind that average
human needs 300-400ms to perform an blink of eye :)

 

So, this makes again another very simple blog post, to summarize plot started by the title,  there is nothing needed to do to serve static resources, if you use Nancy on OWIN. Nancy already takes care of it, same way as it does on ASP.NET, so no need to worry what is underneath.
As this works, now you can start programming :) There is one thing that is from my experience very neglected and many developers don’t know or don’t use it, and that is <base> html tag. It is very useful, especially if you want to create Single-Page or Rich-Client applications, which tend to load lot of resources from JavaScript and don’t have access to Html helpers like Url.Content or Url.Action that you can see all over the place in views in Asp.Net MVC.
To start building some app, I need to add some client-side functionality. If I replace home.html with basic bootstrap template, and add ng-app directive to html tag, I can check if angular works:
Testing angular in page inspector
Testing angular in page inspector

 

And, as it shows ‘it works!’ in place where I have put curly brackets, I’m happy. As this is only static html, Visual Studio Page Inspector will render exactly same result as browser. Now, I’ll add application root to <base> tag, which is by default “/”, but if you ever hosted your application in IIS, and if it was not in root, but in some path (like localhost/myapp) then you know how important was to render all resources with @Url.Content helper, because all you resources would be broken otherwise. So, after I added <base href=’/’ /> and changed css and script links from relative to app-relative (removed ‘../’ prefix), I’m adding project root folder to local iis, into http://localhost/playwithowin app:

 

 

Loading project url in browser shows that OWIN works on IIS, that’s nice, but that also kills css and js resources loading, because they are loaded from root of app, which is now wrong, and it is common thing happening after you put app in virtual folder when you don’t use @Url.Content helpers. Now my angular doesn’t work properly anymore, because it tries to load it from http://localhost/Scripts/angular.js instead of http://localhost/playwithowin/Scripts/angular.js:

 

To fix this, I will fix path in <base> tag: <base href=”playwithowin” />
That makes everything fine again:

 

 

Nice thing about <base> tag is that doesn’t only fix these urls, but as we will see, also removes need to have ‘root’, ‘approot’ or whatever is the name that you use in global javascript namespace to inject that path in master/layout page and to make js code aware of it for needs of loading any static resources asynchronously. For me that was always one of ugliest things in JavaScript, and now you can just forget about it. Just use apprelative paths in your app, and point base tag to your app root, whatever is it.

Next problem is, you may deploy your app to different environments, which may be on same server, in different virtual folders, or you may even want to have multiple instances of application on same server. To automate this, I’ll send base path from server:

 

Screenshot 2014-04-13-18-56-17-6571639
Nancy view can accept anonymous view model, and I assign base path of request url (that is “Nancy root”) to server-side view model.

To use it in view, just use Razor-like syntax in html file! Thanks to The Super Simple View Engine, which is by default used in Nancy, it will be replaced with server variable:

 

So, to summarize this post, so far, using Nancy on OWIN is not different than using it on Asp.Net, and for many cases, Nancy’s Super Simple view engine is more than enough for what you need. If you still need Razor, just install NuGet: RazorEngine.

Next step in creation of app would be adding some custom js and html files. I will add angular app, one view (welcome.html), controller (WelcomeCtrl), and use them in home.html (set app name in ng-app in html tag, add div which references new view, and add references to new js files):

app files and result

 

This is now very simple functionality, but we already have 3 referenced js files. Angular automatically loads views, but js files must be loaded explicitly, and in average application, with well separated responsibilities, there could be hundreds of js files. That could be managed using some AMD framework, but that is one of aspects where Asp.Net rules with bundling & minification, and I like it. It reduces number of requests, and we can leverage caching because it allows to automatically expire cache by varying url. In next post I will be looking on ways how to achieve same thing here.

Source code for this version is pushed to github.

Using Nancy on OWIN

I was keeping my eye on OWIN for some time now (since Mark Rendle’s interview in DNR in 2011, when he complained about HttpRequest and HttpResponse being sealed in ASP.Net and spoke about OWIN as alternative). I like simplicity of this interface, and I also like that Microsoft listened to community and provided Katana, their implementation of it (so now you can also run OWIN apps on IIS). OWIN got to stage where it can be used for serious applications, there is already support for multiple frameworks, some of them being Nancy, Singalr and WebAPI, so you can now build pretty much anything on top of it, and being independent from IIS and all of its http modules, handlers etc has a lot of potential to perform better (given that you don’t need all of these features that asp.net provides, which is the case for most of applications). And those of you who tried testing your code dependent on System.Web, probably already know about OWIN. For just one good reason why to use OWIN, I would just like to quote one part of that interview:

the code’s maintainability is that less code between the TCP socket and your framework. It feels naturally like that’s a good thing and it’s just less code in your application, that’s less code to go wrong. If everything is handled through interfaces or delegates, then at any point in that pipeline you can inject something in a test environment; and as far as everything beyond that point is concern, that might as well have come from a TCP socket so you can create a dictionary of headers and you don’t have to patch in everything else.

quote from transcript on http://s3.amazonaws.com/dnr/dotnetrocks_0683_mark_rendle.pdf

I’m big fan of clean and simple code above all, and I hate additional layers, especially when they don’t provide any valuable abstractions (don’t get me wrong, ASP.Net provides many useful abstractions, and it is great framework, but sometimes there is just no need for all of that), sometimes you just don’t need all that infrastructure, actually I would say that most of applications don’t need it, especially today when more and more applications are running in browser, you just need as simple way as possible for your application to communicate to server.

So, as I always want to learn something and extend my skill set, I choose to put OWIN under my belt, as creating HTTP services which can be self-hosted (or in windows service, or in exe/scheduled task, or…) can come in pretty handy.

To get started with OWIN, I’m using Visual Studio 2013, it takes few simple steps:

Create new application
Create new application

This gives you choose template screen:

Choose template
Choose template

That gives new project that is (aside from plenty references) empty, it contains only web.config.

Project contents
Project contents

If you are not using Resharper, then you should :), but for this matter you can use some other extension to clean up unused references, that will leave your project with only System and System.Core. To get started with Nancy and Owin, use NuGet PM Console: Install-Package Nancy.Owin. That will also pull Nancy, as dependency. That puts Nancy, Owin, and Nancy.Owin into references. After that, project looks like this:

References
References

To run app, you need to host it somewhere. As most convenient way to develop is to run it from Visual Studio, it is necessary to add hosting adapter to host OWIN in IIS (or Express version that is used by Visual Studio):

Install-Package Microsoft.Owin.Host.SystemWeb

This adds Microsoft implementation of Open Web Interface (aka Project Katana) and hosting adapter which contains OwinHttpHandler used to handle http requests and pass them to OWIN. These are in Microsoft.Owin, and Microsoft.Owin.Host.SystemWeb libraries, respectfully.

 

 

 

 

After these few steps, it is possible to run this frame for application:

Exception when there is no app in Owin
Exception when there is no app in Owin

 As this is not MVC application from VS template, this is expected, but it is very nice and descriptive exception, and it makes clear what is next step to do to get it working: it is necessary to either add OwinStartup attribute to assembly, or to create Startup class with Configuration method. As “Startup.Configuration” sounds explanatory, I will do that:

Startup class

Configuration method’s signature is documented in Katana documentation, but you don’t even have to open it, if you don’t make it like this, another exception will tell you to do it. This part is actually what is this whole post about. This single line of code in Configuration method is actually all you need to do to run Nancy on OWIN.

It is worth noting that IAppBuilder is not official part of OWIN interface, but part of Katana itself, and if you decide to run your app on something else, then it may be necessary to change way how application starts.

 

 

UseNancy extension method comes from Nancy.Owin package, and it is just wrapper around builder.Use:

UseNancy

If you take a look into NancyOwinHost, you will see that it is just an adapter to Owin infrastructure, similar to NancyHandler for Asp.Net, but difference is that handler gets to work with HttpContextBase (which is abstract, and not very simple to mock/fake), while NancyOwinHost gets Dictionary<string,object> which is how http request is represented in Owin. It is lower level of abstraction, meaning it is much closer to the metal, and if you don’t need all of the fancy stuff in HttpContext, then it is likely that this is going to perform better, with less resources.

Running application now gives default Nancy 404 response:

404

 

Ok, Nancy gets request, and as there is nothing to process it, returns not found.

 

 

 

 

 

To return something useful to client, we need a “controller”. In Nancy, that is Module:

Screenshot 2014-04-13-00-22-57-8748768

This is how handler for get request for root path (“/”) is defined in Nancy. I like it, as to me is much more expressive than “Index” ActionResult.

 

 

 

 

 

As I’m returning view named “home”, I will create it in “Views” folder (standard convention, Nancy will look for it there):

home.html
home.html

And result is:

result
result

 

 

 

 

 

So, our web site in .NET without System.Web is live:

Project structure
Project structure

 

 

This is yet far away from being an application, but building one using Nancy and Owin is not so much different than using MVC and Asp.Net. It is always useful to learn other ways to do same thing, because that gives you another perspective and ability to see things you missed before.

I end this post here, and next step will be more about Nancy, and how to add some script and css resources and see how to serve them to browser, and what is different in OWIN than in Asp.Net, as standard bundling libraries reside on top of System.Web and won’t work here.

 

I pushed source code for playwithowin project to github. You will have to restore NuGet packages as only code is there, so don’t go offline until you build it once :)

 

UPDATE: Next post is now published

Vodič za napuštanje BiH – odlazak u Njemačku

Ovaj blogpost je ispunjenje moga obećanja mnogobrojnim prijateljima i kolegama koji su me pitali “Kako si uspio pronaći posao?”, “Gdje si našao poslodavca?”, “Šta su te pitali?”, “Koliko ti je vremena trebalo?” i mnoga druga pitanja, a ja sam obećao da ću napisati odgovore, da se ne ponavljam, pošto zadnjih par godina nikako nemam viška vremena :)

Pošto su moje aktivnosti ponovo počele da poprimaju neke obrasce, pronašao sam malo vremena da počnem da pišem o ovoj temi, a ukoliko nešto izostavim, pitajte u komentarima, pa ću da obradim i to što vas zanima.

Na samom početku – prvo da pojasnim šta opisujem, i koji su bili moji motivi, pošto će nekima sigurno biti interesantniji prvi, jednostavniji model. Na rad u EU je moguće otići i ako ste zaposleni u firmi van EU, kao detaširani radnik, i vizu za to je relativno lako dobiti, jer možete da se obratite direktno recruiting agencijama koje će vas prodati krajnjem klijentu, u tom slučaju idete samo privremeno raditi, jer viza vrijedi samo za taj angažman, a ta firma u koju idete će vašoj firmi koja vas šalje najvjerovatnije potpisati izjavu da vas neće pokušati zaposliti (jer vaš poslodavac u BiH ne želi ostati bez radnika). Od samog boravka u EU možete očekivati neku dnevnicu ili dodatke povrh plate koju inače primate, tako da možete “vidjeti svijeta” (ako su vas poslali u zanimljiv grad) ili uštediti ako se toga odreknete. Mene to nije zanimalo jer time ne rješavam svoj status koji je u BiH bio bez ikakve perspektive, puko sastavljanje kraja s krajem, bez izgleda da se u idućih nekoliko godina bilo šta značajnije promijeni: moja karijera, ženino zaposlenje, kvalitet života…  Zapravo, izdaci su se zahvaljujući skoro svakodnevnim poskupljenjima povećavali brže nego primanja tako da se to mijenjalo, ali nagore. Dakle, moj cilj, ka kome sam napravio veliki korak, je da obezbijedim svojoj porodici neku perspektivu, da mogu da obezbijedim djetetu vrtić, da ne razmišljam kako ću mu kupiti bicikl, autosjedalicu, igračku, da ne moram strijepiti hoće li mi neko napasti dijete ili udariti autom vozeći kroz crveno “jer mu se može”… Neki će reći da se to može dogoditi bilo gdje, i to je istina, ali ko god je bio u uređenom društvu ne može poreći da je takvih stvari daleko manje i da je prekršitelja daleko manje (pošto su kazne brže, češće i bliže postignut je daleko veći stepen uređenosti i kultivisanosti), a isti ljudi koji poštuju zakon ovdje (u EU), kada dođu u zavičaj ga krše, jer je mala vjerovatnoća da će biti uhvaćeni, a velika da će i ako budu lako podmititi policajca. Uglavnom, oni koji ovo čitaju već znaju koliko naopako funkcioniše sistem u BiH i tu nema šta da se dodaje ili opisuje, ko god želi može da vidi koliko je sve pogrešno. Iz ove pozicije, moje divljenje odlazi onima koji mogu da odu ali ipak imaju hrabrosti da ostanu živjeti u neizvjesnosti.

Dakle, da biste dobili vizu za zaposlenje u Njemačkoj, osnovna stvar je da dokažete nekome (poslodavcu) u Njemačkoj da ste mu potrebni (baš vi). Ukoliko posjedujete neko strogo specifično znanje ili vještine, moguće je dobiti vizu čak i ako nemate formalno obrazovanje / fakultet (naravno, mnogo teže jer čak i u Njemačkoj ima nezaposlenih, i kada se ne radi o visoko obrazovanim radnicima, njemački državljani imaju prioritet). Ukoliko imate visoko obrazovanje, potrebno je i odlično znanje engleskog jezika, i vrlo poželjno njemačkog (ovo nije u potpunosti nužno, ali između dva kandidata od kojih jedan zna njemački, on uvijek ima veliku prednost). Što se tiče prizanja vaše diplome, resurs je anabin.de, gdje možete pronaći svoj fakultet i provjeriti da li ima H+ status (H+ status znači da je program priznat u potpunosti). Koliko sam uspio vidjeti, svi fakulteti državnih unverziteta u BiH imaju taj status.  Takođe, ukoliko odlično znate njemački, moguće je proći bez engleskog, ukoliko ne tražite posao u IT industriji. Najbolji resurs za sve informacije i veze ka drugim sajtovima je make-it-in-Germany. Što se tiče posla, posla ima, mnogo. Međutim, bar što se tiče posla u IT sektoru, skoro svi oglasi koje ćete pronaći na internetu za poslove vas vode recruiting agencijama. Razlog je jednostavan, velike firme, giganti, koji zapošljavaju najviše ljudi, na zapadu funkcionišu drugačije nego “kod nas”: nema odjela za ljudske resurse, nema knjigovodstva, obračuna plata, firma radi ono što joj je primarna djelatnost. Sve ostalo se “outsourc-a”, u ovom slučaju recruiting agencijama, preko kojih velike firme zapošljavaju skoro svo ljudstvo. Njihov cilj je imati na kraju mjeseca jedan račun/iznos (ili npr. dva, ukoliko ljudi dolaze iz 2 različite agencije), koji firma isplaćuje za sve lične dohotke i vezane troškove, bez komplikacija, obračuna, platnih lista… A kada zapošljavaju, dodatna prednost upotrebe agencije je što je u Njemačkoj ogromna mobilnost radne snage, i recruiting agencije već imaju ogromnu bazu stručnjaka iz koje mogu lako da im nađu odgovarajući profil kojem upravo ili uskoro završava projekat i može da dođe na idući. No, posla je više nego stručnjaka, i za ovo kratko vrijeme koje sam ovdje više je nego očigledno – velika je potražnja za dobrim ljudima, i to ne vrhunskog kalibra jer takvih je jako malo, ovdje su i natprosječni jako traženi (u timu od 20+ ljudi nema niko rođen u Njemačkoj, ima samo jedan član tima koji živi u Njemačkoj zadnjih 12 godina, ostali su svi sa strane). A same recruiting agencije ne zapošljavaju nikoga, one samo angažuju firme-podizvođače koje šalju ljude ovim prvima. U toj činjenici leži problem svih koji žele pronaći posao a nemaju vizu, jer oglasi ništa ne znače – recruiting agencije vas ne mogu zaposliti. Da biste dobili vizu koja vam omogućava da se doselite raditi u Njemačku, potrebno je da imate firmu u Njemačkoj koja će vam poslati ugovor o radu. Takvih je mnogo, ali treba ih tražiti pod imenom “[nešto] professionals”, “[nešto] solutions/services”, “staffing agency” i sl. Takve će vas prodati prvoj recruiting agenciji, za par stotina evra dnevno, ali to ne treba niti da vas zanima niti da vam bude krivo, jer jedino što je bitno je da dobijete ugovor koji vam garantuje minimalno 46.400 evra bruto godišnje, ili 36.192 ukoliko ste stručnjak iz polja matematike, informatike, prirodnih nauka ili tehnike, što su minimalni iznosi da biste dobili plavu kartu (Blue Card), a i sa minimalnom platom ćete sigurno živjeti bolje nego sa platom od 1000 evra u BiH. Na kraju krajeva, prva plava karta nakon 21 mjeseca (ukoliko položite B1 nivo njemačkog) može da se zamijeni za trajnu, koja nije vezana za poslodavca, i onda ste u situaciji da možete slobodno da mijenjate poslove i birate poslodavca (čak i da osnujete svoju firmu/obrt i onda prodajete sami sebe direktno recruiteru).

Da biste pronašli posao, preporučujem berzu poslova Njemačkog biroa za zapošljavanje: http://jobboerse.arbeitsagentur.de/ – tu sam i sam pronašao poslodavca.
Nakon što se registrujete kod njih, dobićete poštom inicijalni pin kojim ćete verifikovati svoju adresu, i onda možete koristiti sistem da pronađete posao. Tu ima mnogo više oglasa pravih firmi, koje ne traže contractor-e i koje mogu da vas zaposle. Ti oglasi su često generički, i postavljeni su sa ciljem da se nađe neko koga mogu lako preprodati recruiting agencijama, a same navedene vještine i iskustvo možda nisu tačne, odnosno recruiter može da traži nešto drugo, pa ništa ne košta da se prijavite i na poziciju koja nije baš 100% za vas, bitno je da napišete šta tačno znate, i kakvo iskustvo imate. Takođe, ukoliko vidite da je firma u koju se prijavljujete neka staffing/consulting agencija, ili ako vidite da su oni to po tome što traže da pošaljete svoj cv, listu projekata, sliku i sl (kreiraju vaš profil), objasnite im da će ako vam pronađu posao preko agencije, trebati minimalno mjesec dana do momenta kad možete početi raditi, možda i više, i da bi bilo dobro da vam pošalju ugovor ili obavezujuću ponudu sa kojom možete dobiti vizu, tako da možete brže biti raspoloživi kada vam nađu poziciju.

Što se tiče dobijanja posla, najviše bodova vam mogu donijeti preporuka od nekog iz Njemačke, odlično poznavanje njemačkog jezika, ili da neki recruiter koji vas je intervjuisao potvrdi da vam može lako pronaći poziciju. Ja sam imao preporuku od developera iz Njemačke, koji je bio voljan da telefonom potvrdi moje vještine i ličnost. Upoznao sam ga preko freelancing sajtova (elance, odesk) i za njegovu firmu odlično odradio par poslova. To ne zahtijeva previše vremena (ukoliko uspijete bez reputacije dobiti freelancing posao za nekog u Njemačkoj). Pametno je imati Europass CV, to je format u kom vam niko neće ništa zamjeriti, a ako poslodavac ima svoj template, popunite i to, kod njih se svaki trud cijeni. Takođe, jako je bitno da napravite nekakav excel u kome ćete nabrojati projekte na kojima ste radili, firme za koje su ti projekti rađeni, ako postoje adrese do web sajtova, trajanje od-do, vaša uloga na projektu i tehnologije koje ste pritom koristili. Ponavljam, posla ima, sa mnom rade ljudi iz Rumunije, Bugarske (oni su tamo zaposleni i ovde ih je poslala firma), Moldavije, Južne Afrike, Indije, Pakistana, Rusije… Ne bi svi bili ovde da ne nedostaje  radne snage. Samo je potrebno biti uporan i ne gubiti nadu. Slanje CV ne košta skoro ništa, a ako zakucate na dovoljno vrata, neko će sigurno otvoriti. Potrebno je imati samopouzdanja i biti uvjeren da su vaše vještine dovoljne da vas neko zaposli, i potruditi se da pokažete da znate dovoljno da će se njima isplatiti da vas zaposle. Kada počnu da vas zovu telefonom, ukoliko trebate da vi njih nazovete, ili žele da vas intervjuišu, uplatite Skype kredit i zovite ih sa Skype na njemačke fiksne linije (to vas košta oko 2 centa po minuti), i recite da je tako daleko jeftinije. To je mala investicija ali pokazuje da ste spremni preuzeti inicijativu i da ne čekate da neko dođe po vas.

Sam proces dobijanja vize je, isključivo zbog predaje aplikacije u Sarajevu, vjerovatno najkomplikovaniji korak cijelog odlaska, ali uz par informacija može biti lakši. Trenutni skup dokumenata koji je potreban se može vidjeti ovdje. Obrazac za vizu je takođe dostupan na sajtu ambasade u Sarajevu. Ukoliko imate ugovor na neodređeno vrijeme, za predviđeno trajanje boravka stavljate “unbefristet” (trajno). Što se tiče zdravstvenog osiguranja, ne morate stavljati da ga imate niti ga plaćati, jer oni znaju da ćete biti osigurani kada budete zaposleni. Diplome prevedite kod sudskog tumača, i tražite da imaju Apostille pečat, time prevodi postaju važeći dokumenti bez prisutstva originala (ali zbog needukovanog osoblja na ulazu u ambasadu koje vas neće pustiti, obavezno ponesite originale na uvid, i njihove fotokopije, fotokopije vam ne trebaju za vizu, ali treba da biste došli do šaltera, nažalost). Zahtjevi za vize idu u Njemačku srijedom, tako da vam je svejedno da li ste predali zahtjev u četvrtak ili idući utorak. Mene su nazvali da je viza odobrena 6 dana nakon te srijede (prvi sljedeći utorak). Pametno je, ukoliko znate da nećete putovati, ostaviti pasoš u ambasadi, i 15KM da vam ga pošalju FedEx-om kada zahtjev bude obrađen. Time štedite vrijeme i novac za još jedan put u Sarajevo, ako ne živite u istom. Još jedna vrlo bitna napomena, kada dođete po vizu, prijavite se radniku na ulazu, jer oni koji podižu vizu ne moraju čekati skupa sa onima što podnose, jer podizanje vize traje 5 minuta. Takođe, kada ste gore na šalteru, možete zamoliti ostale koje čekaju da vas puste da podignete vizu, jer predavanje traje pola sata a podizanje 5 minuta, vjerovatno vam niko neće praviti problem.

Viza se dobija na 90 dana, i ima svrhu dok vam ne budu gotovi elektronska boravišna dozvola i plava karta. Za podnošenje zahtjeva za plavu kartu vam je potreban pasoš sa vizom, diploma (nije naodmet ponijeti prevod, ali to će ured za strance već imati, jer se javljate istom uredu koji vam je odobrio vizu, u mjestu poslodavca koji vas je zaposlio), i 110 evra (ovo možete platiti i kada dođete podići plavu kartu). Cijeli proces traje oko 25 minuta, potrebno je da popunite jedan zahtjev, date otiske sa 2 prsta i visinu. Izrada plave karte traje 2-4 sedmice, i izdaje se na trajanje ugovora o radu (ako je na neodređeno onda se smatra da je ugovor na 4 godine) + 3 mjeseca, ili ukoliko vam pasoš ističe prije tog datuma, onda važi koliko i pasoš.

Informacije vezane za vizu za spajanje porodice su takođe dostupne na sajtu ambasade. Ovdje ne piše, ali bračni drugovi nosioca plave karte ne moraju prilagati dokaz o poznavanju njemačkog jezika (ovo ću još provjeriti kada moja porodica bude podnosila zahtjev), a osim toga, bračni drug nosioca plave karte takođe ima pravo da dobije istu, koja predstavlja i radnu dozvolu, te ne mora čekati 2 godine da bi tražio posao, što je slučaj kada se osnov spajanja porodice osoba koja ima boravišnu dozvolu ali nema plavu kartu.

Vjerovatno će svima najveća briga biti budžet, jer sam odlazak nema smisla ako je ekonomska održivost upitna. Za ove “početne” plate od oko 35-45 hiljada evra (kakvu ćete i tražiti jer ne možete očekivati da će vam ponuditi više “na neviđeno”) možete očekivati da će vam neto iznos, ukoliko niste u braku, biti oko 61% od bruto iznosa, dakle kao u BiH (s tim da ćete za razliku dobiti značajno bolje zdravstveno osiguranje i ulog u penzionom sistemu koji se mooožda neće raspasti dok vi dočekate penziju). Ukoliko ste u braku, i vaš bračni partner ima manja ili nikakva primanja, tada spadate u “Steuerklasse III”, koja je manje oporezovana i možete očekivati blizu 70% od bruto iznosa. Dodajte na to oko 2000 evra godišnje dječijeg dodatka, po svakom djetetu i imate otprilike budžet. S obzirom da ćete stan u Njemačkoj i u najskupljim gradovima kao što su Minhen ili Frankfurt pronaći za manje od 1000 evra sa režijama (ovo je baš najgori mogući ishod, najbolje da provjerite ovdje sami za koliko možete pronaći stan, često će to biti i ispod 500 evra sa režijama, ne samo u malim gradovima, Berlin npr ima jako jeftine stanove, čak i za kupovinu, cijena se kreće oko 900 evra po kvadratu), to znači da možete računati sa najmanje 1000 evra za ostale potrebe. Vjerujem da je to više nego što bilo ko ko čita ove redove sada ima kao budžet nakon plaćanja stana i režija. Pri tome je potrebno imati na umu da što se tiče cijena, očekujete skuplji stan i režije, a ukoliko ne pušite sve ostalo će biti značajno jeftinije (uz malo praćenja akcija i sl. svi ostali troškovi mogu biti i do duplo jeftiniji nego u BiH). Dobar resurs za to je kaufda.de. Čak i ako budete trošili isto kao u BiH, ponovo ćete imati pozitivan iznos na kraju mjeseca. Plus, za svako dijete po oko 190 evra mjesečno, do 23. godine djeteta, znači da možete da planirate i proširenje porodice.

Umalo sam zaboravio, ukoliko vas prodaju kao konsultanta, velike firme koje zapošljavaju kontraktore često plaćaju i sve troškove (to se zove All-Ex contract, kada krajnji klijent plaća sve troškove). Pod tim se, u mom slučaju, podrazumijeva smještaj u hotelu, hrana, pranje veša, prevoz između hotela i firme (autobus, pošto su contractor-i smješteni u 3 hotela koji su blizu međusobno pa ih autobus kupi ujutro i razvozi popodne), let kući svake 3 sedmice (4. se radi od kuće), ili za one koji su bliže, let kući svaki vikend. Ukoliko ne dobijete ovakav ugovor, vjerovatno ćete imati neki dodatak na platu koji će pokrivati odvojeni smještaj dok vam se porodica ne doseli u Njemačku.

To je sve za sada. Uskoro ću da provjerim koliko mora da se plati polaganje vozačkog ispita (BiH vozačka važi 6 mjeseci nakon doseljenja, ako imate Hrvatsku ili Slovenačku možete je zamijeniti za Fuhrerschein), pa ću dopuniti članak sa tom informacijom, i sa odgovorima ukoliko bude pitanja.

 

Script resource localization in ASP.NET MVC

As modern web applications are becoming more and more reliant on JavaScript, and world of SPA is getting new members every day, I wanted to be able to localize JavaScript resources, so my dialogs and other JS-generated gui is localized.

As I’m doing development in ASP.NET, I already use resx files for my resources. And, with having my plan to localize SPA without reload, logical first step would be to be able to get localized resource values as JSON. So, I made simple ScriptsController and turned it into snippet for VS.

You can take this snippet, create ScriptsController.cs as empty mvc controller, and then use snippet inside your namespace to replace complete ScriptsController class. The only thing you need to replace is alias for Resource in using directives:

script controller

 

This works as it is for JSON request, but for standard request, you also need to add Resources.cshtml view, also available as snippet. This view basically creates a <script> tag with JS variable named Resources by default, which contains all items in it:

Resource.cshtml

 

How this looks like in practice?

JSON request:

json resource request

 

 

 

“Normal” request:

text resources requestresponse window - resource

 

 

 

 

 

 

 

 

 

In next post, I will use these resources to change localization language in Single Page App without reload.

Composite keys in EF CodeFirst

 

It is not very often a case that you need composite key in your db, but when you have such domain then you cannot make a good model if your orm tool does not support composite keys. EF CodeFirst has recently improved this support (last time I needed it it was not any good), but there are not many resources/samples out there. Here is one.

Model:

addressIt is a simple hierarchy with no surrogate, only natural keys. Address object/table actually contains all the data as there are no additional attributes in other entities, but this is only a example, and you can easily imagine that you have additional properties in i.e. city (coordinates, or link to map). If you don’t need additional properties in your entities, then you can tell EF modelBuilder to create complex types for them and you will have composite keys automatically.

One downside of this “manual” approach is that you need to have both primary key and related object property in your entity (i.e. State has string Country_Name and Country Country properties), but that is not a big problem, and in most scenarios you will want that as you will have data that you need without join or loading another object (that is the purpose of natural keys).


address-db

This is the db schema that I want, each dependent object inherits primary keys from its principal, so when I read Address record, I already have all the data that I need, and in at least 90% of reads there is no need to do join with other tables.

This diagram is actually created from the database which was created from my model, using EF CodeFirst. To get these composite primary keys, I used mappings described below.


Mapping configuration (in DbContext.OnModelCreating):

modelBuilder.Entity<Country>().HasKey(c => c.Name)
.HasMany(c => c.States)
.WithRequired(s => s.Country)
.HasForeignKey(s => s.Country_Name);

modelBuilder.Entity<State>().HasKey(s => new { s.Country_Name, s.Name })
.HasMany(s => s.Cities)
.WithRequired(c => c.State)
.HasForeignKey(c => new { c.Country_Name, c.State_Name });
modelBuilder.Entity<City>().HasKey(c => new { c.Country_Name, c.State_Name, Name = c.Name })
.HasMany(c => c.Streets)
.WithRequired(s => s.City)
.HasForeignKey(s => new { s.Country_Name, s.State_Name, s.City_Name });
modelBuilder.Entity<Street>().HasKey(s => new { s.Country_Name, s.State_Name, s.City_Name, s.Name })
.HasMany(s => s.Addresses)
.WithRequired(a => a.Street)
.HasForeignKey(a => new { a.Country_Name, a.State_Name, a.City_Name, a.Street_Name });
modelBuilder.Entity<Address>().HasKey(a => new
{
a.Country_Name,
a.State_Name,
a.City_Name,
a.Street_Name,
a.Number,
a.ZIP,
a.Line1,
a.Line2
});



Note that EF will by default choose nvarchar(128) for primary keys. As nchar has better properties when used as primary key or index in rdbms, I configured my primary keys to be nchar:

var keytype = "nchar";
int keylength = 50;
modelBuilder.Entity<Country>().Property(c => c.Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<State>().Property(c => c.Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<State>().Property(c => c.Country_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<City>().Property(c => c.Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<City>().Property(c => c.State_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<City>().Property(c => c.Country_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<Street>().Property(c => c.Name).HasColumnType(keytype).HasMaxLength(80);
modelBuilder.Entity<Street>().Property(c => c.City_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<Street>().Property(c => c.State_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<Street>().Property(c => c.Country_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<Address>().Property(c => c.Street_Name).HasColumnType(keytype).HasMaxLength(80);
modelBuilder.Entity<Address>().Property(c => c.City_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<Address>().Property(c => c.State_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<Address>().Property(c => c.Country_Name).HasColumnType(keytype).HasMaxLength(keylength);
modelBuilder.Entity<Address>().Property(c => c.Number).HasColumnType(keytype).HasMaxLength(20);
modelBuilder.Entity<Address>().Property(c => c.ZIP).HasColumnType(keytype).HasMaxLength(5);
modelBuilder.Entity<Address>().Property(c => c.Line1).HasColumnType(keytype).HasMaxLength(50);
modelBuilder.Entity<Address>().Property(c => c.Line2).HasColumnType(keytype).HasMaxLength(50);

kick it on DotNetKicks.com

Why uptime on WP7 cannot be longer than 24.9 days?

This morning I saw in System View on my Samsung Omnia 7 that uptime is “more than 24.9 days”, and boot time is “earlier than 30-Dec-11 13:07:24”. At first I was amazed, how can it be “earlier than”, and how that reference in time is not fixed (it was 29-Dec yesterday). Then I realized that phone does not “remember” its time of boot, but has some sort of incrementing register for counting uptime, and it hits its limit on 24.9 days. It would be interesting for how long this phone can work without reboot, as it seems very stable, but it seems that cannot be known without manual recording of boot time Disappointed smile.

I did some calculations, and it seems that phone is using SIGNED int as register value which counts number of MILISECONDS since boot. As 25 days has about 2’160’000’000 milliseconds, and 2^31 is 2’147’483’648, it starts to seem logical where did number 24.9 days came from Nerd smile. It is logical that boot time itself is not recorded, as there it would be a possibility of reporting “fake” uptimes by setting the clock on the phone. However, in my opinion, method used is also not optimal.

So, what could be better here? Light bulb

- For start, it could be unsigned int, so the OS would be able to keep track for more than 49 days of uptime.
– It could also count seconds instead of milliseconds, that would make possible to count more than 1300 years of uptime Smile, or if for some reason needs to keep milliseconds (i.e. does not want to break all existing functionalities?), unsigned long (int64) could be used (although I don’t remember if it is available in WP7), to give overkilling amount of almost 585 millions of years Hot smile.

All this considered, it seems that 49 days would be enough, change would not break anything, and it requires changing only one variable declaration.

Check which rule is not fullfiled in jQuery validate plugin

Recently, I have encountered a situation where I used jQuery validation plugin and needed to know which of validation rules are failing. After asking this question on http://stackoverflow.com/questions/7648727/jquery-validate-check-which-rule-is-not-fullfiled and receiving no answers for 15 days, I have spent some time to solve it by myself.

It turned out quite easy, after inspecting source code of plugin on https://github.com/jzaefferer/jquery-validation/blob/master/jquery.validate.js, I have found out that this can be done by adding my own function to it:

 

$.validator.prototype.ruleValidationStatus = function( element ) {
    element = $(element)[0];
    var rules = $(element).rules();
    var errors ={};
    for (var method in rules ) {
        var rule = { method: method, parameters: rules[method] };
        try {
            var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
 
            errors[rule.method] = result ;
 
        } catch(e) {
            console.log(e);
        }
    }
    return errors;
}

This function returns list of validation rules with their results, and usage is simple:

$("#myform").validate().ruleValidationStatus($("#myField"));

Simplify common data access functions by using Entity Framework extension points

 

Whenever there is a new project with database, there is substantial amount of time spent on design of that database, as changes to database later cause much more overhead and problems than in beginning. In today’s conditions, however, it is very rare that database schema is not changed even during implementation (or immediately after deployment Smile). That is one of reasons why we now have CodeFirst workflow in EntityFramework.  It is great to have one common set of properties in one place (base object) inherited into all tables (i.e. UserCreated, DateCreated etc), and not having to think about it in individual objects.

It is even better to have all logic that uses those common properties in one place, but that tends to be hard to implement if repository pattern is used with all “common” logic implemented in common repository containing basic CRUD operations and data context as a dependency object. The problem is that each repository will inherit from common repository, and all will have “same” behavior, but EF allows you to save complex objects at once, and this can make your life bitter when you have common repository. The thing is, your custom behavior is executed for object you are saving, but not for referenced objects which are also saved when you add or update your main object. Workaround is to have instance of repository for each type which is referenced in your main object, save each first through “its” repository, and then save your main object which references all of them. As thing always can be made better (and better is more simple for me), I tried to find an answer for this problem. My answer is on github and if you are interested check it out (it has sample which works out of the box), and read description here.

There is a simple solution for this problem – common repository is code first context! It has couple of extension points (virtual methods left which can be overriden) where you can implement your own logic to handle journaling, validation, business rules… Almost everyone who worked with CF has used (overriden) OnModelCreating method, as it is very common in tutorials, but there are couple more:

bool ShouldValidateEntity(DbEntityEntry entityEntry)

System.Data.Entity.Validation.DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)

int SaveChanges()

ShouldValidateEntity and ValidateEntity are usefull places to call from your business rules and all possible validators, as there is no way that something will go to database by not passing through these (often ignored methods). These extension points are fairly simple to use and domain-specific, and I will not write about them in this post. My target of interest is SaveChanges.

go.DB.JournalingBase is simple project featuring usage of EntityFramework CodeFirst and overriding SaveChanges method of DBContext in order to keep record of changes on entities in database. There is a simple usage sample project and a test project with couple of test cases to confirm that everything is working. Database is SQLCompact, so no SQL Server is necessary and everything works on “F5”.

This is the idea: I have one “base” object – JEntity from my database objects inherit, and have corresponding DBContext, from which my repository(ies) inherit. Common object has Id property and other common properties I want all my journaling objects to have:

public abstract class JEntity
    {
        /// &lt;summary&gt;
        /// Gets or sets the id.
        /// &lt;/summary&gt;
        /// &lt;value&gt;The id.&lt;/value&gt;
        public int Id { get; set; }
 
        /// &lt;summary&gt;
        /// Gets or sets the original id.
        /// &lt;/summary&gt;
        /// &lt;value&gt;The original id.&lt;/value&gt;
        public int OriginalId { get; set; }
 
        /// &lt;summary&gt;
        /// Gets or sets the date created.
        /// &lt;/summary&gt;
        /// &lt;value&gt;The date created.&lt;/value&gt;
        public DateTime DateCreated { get; set; }
 
        /// &lt;summary&gt;
        /// Gets or sets the date deleted.
        /// &lt;/summary&gt;
        /// &lt;value&gt;The date deleted.&lt;/value&gt;
        public DateTime? DateDeleted { get; set; }
 
        /// &lt;summary&gt;
        /// Gets or sets the user created.
        /// &lt;/summary&gt;
        /// &lt;value&gt;The user created.&lt;/value&gt;
        public string UserCreated { get; set; }
 
        /// &lt;summary&gt;
        /// Gets or sets the user deleted.
        /// &lt;/summary&gt;
        /// &lt;value&gt;The user deleted.&lt;/value&gt;
        public string UserDeleted { get; set; }
    }

This object has OriginalId property, as a reference to “original” object – the first one that was added to database. When objects are updated, new version is created each time, “old” object is marked as deleted (DateDeleted is set in this case). All versions of same object share same OriginalId value, which is the same as Id value of oldest version.

Mapping to database is done using IEntityMap class, so this one is clean and simple, and does not have database metadata. The reason is that in real life you often have to refactor your code and change something. If model is created from metadata, then any change will cause your existing database to be “broken” and you will have to recreate it. This is good strategy in the beginning when you initialize your database with test data every time and test through unit tests, but if you have some staging environment where application is deployed and tested by users/testers they may have problems with that (whereee areee all thoose records I entered in friday?? Smile). This is especially important if you are making some serious enterprise application that will have longer lifecycle, and you want to make support easier (we do not want to have a “bomb” which will delete production database).

public IEntityMap()
	{
		//// Primary key
		this.HasKey(t => t.Id);
 
		//// Properties
 
		this.Property(t => t.OriginalId)
			.IsRequired();
 
		this.Property(t => t.DateCreated)
			.IsRequired();
 
		this.Property(t => t.DateDeleted)
			.IsRequired();
 
		this.Property(t => t.UserCreated)
			.IsRequired()
			.HasMaxLength(50);
 
		this.Property(t => t.UserDeleted)
			.IsOptional()
			.HasMaxLength(50);
 
		//// Column mappings
		this.Property(t => t.Id).HasColumnName("Id");
 
		this.Property(t => t.DateCreated).HasColumnName("DateCreated");
 
		this.Property(t => t.OriginalId).HasColumnName("OriginalId");
 
		this.Property(t => t.DateDeleted).HasColumnName("DateDeleted");
 
		this.Property(t => t.UserCreated).HasColumnName("UserCreated");
 
		this.Property(t => t.UserDeleted).HasColumnName("UserDeleted");
	}


So,  separate mapping class allows you to refactor properties without having to change their names in database, or to manually sync your database with your model, as everything is clean and readable.

The context – JContext overrides SaveChanges method, which takes care of actions necessary for journaling:

public override int SaveChanges()
{
	// We need same time for all entities updated in same transaction.
	DateTime now = DateTime.Now;
	// Get reference to user to avoid multiple getter calls.
	string user = System.Threading.Thread.CurrentPrincipal.Identity.Name;
 
	//// Detect changes in case that change tracking is turned off
	if (!this.Configuration.AutoDetectChangesEnabled)
	{
		this.ChangeTracker.DetectChanges();
	}
	List&lt;JEntity&gt; insertedList = new List&lt;JEntity&gt;();
	List&lt;JEntity&gt; invalidList = new List&lt;JEntity&gt;();
	foreach (var entry in this.ChangeTracker.Entries())
	{
		// Make sure that this customized save changes executes only for entities that
		// inherit from our base entity (IEntity)
		var entity = (entry.Entity as JEntity);
		if (entity == null) continue;
 
		switch (entry.State)
		{
			// In case entity is added, we need to set OriginalId AFTER it was saved to
			// database, as Id is generated by database and cannot be known in advance.
			// That is why we save reference to this object into insertedList and update
			// original id after object was saved.
			case System.Data.EntityState.Added:
				entity.UserCreated = user;
				entity.DateCreated = now;
				insertedList.Add(entity);
				break;
 
			// Deleted entity should only be marked as deleted.
			case System.Data.EntityState.Deleted:
				if (!entity.IsActive(now))
				{
					invalidList.Add(entity);
					continue;
				}
				entry.Reload();
				entity.DateDeleted = now;
				entity.UserDeleted = user;
				break;
 
			case System.Data.EntityState.Detached:
				break;
 
			case System.Data.EntityState.Modified:
				if (!entity.IsActive(now))
				{
					invalidList.Add(entity);
					continue;
				}
				entity.UserCreated = user;
				entity.DateCreated = now;
 
				JEntity newVersion = this.Set(entity.GetType()).Create(entity.GetType()) as JEntity;
				newVersion = this.Set(entity.GetType()).Add(newVersion) as JEntity;
				this.Entry(newVersion).CurrentValues.SetValues(entity);
 
				this.Entry(entity).Reload();
 
				entity.DateDeleted = newVersion.DateCreated;
				entity.UserDeleted = user;
				break;
			case System.Data.EntityState.Unchanged:
				break;
			default:
				break;
		}
	}
	if (invalidList.Count == 1)
	{
		throw new InvalidJournalingEntityException(invalidList[0], invalidList[0].GetType().Name);
	}
	else if (invalidList.Count &gt; 1)
	{
		throw new MultipleInvalidJournalingEntityException(invalidList);
	}
	int result = base.SaveChanges();
 
	if (insertedList.Count &gt; 0)
	{
		insertedList.ForEach(t =&gt; t.OriginalId = t.Id);
		base.SaveChanges();
	}
 
	return result;
}


The method handles cases when object is added, modified or deleted. When added, it must save reference to it and set OriginalId after it was assigned Id. As object does not have Id until sql server generates one for it, this has to be done after SaveChanges. Theese few lines should in serious system be inside one transaction, just in case.

When object is changed, change is canceled and  only DateDeleted and UserDeleted is set (same as when object is deleted). Instead, new object is added as new version of changed object.

All this is used from sample project, where new entities and context are created, with no code for usage of theese features except inheritance from JEntity and JContext.

If something is not clear, the best option is to start test project and set breakpoints at places of interest, or ask your question in comments!

kick it on DotNetKicks.com

Solution for VHD_BOOT_HOST_VOLUME_NOT_ENOUGH_SPACE error in windows 8

If you are using VHD method of installing windows 8 to virtual disk on physical machine (Scot Hansellman has great tutorial: http://www.hanselman.com/blog/GuideToInstallingAndBootingWindows8DeveloperPreviewOffAVHDVirtualHardDisk.aspx) and you get VHD_BOOT_HOST_VOLUME_NOT_ENOUGH_SPACE error after installation, then your problem is probably dynamic VHD and not enough free space on disk containing that drive. I had the same problem, and googling for it did not solve it, as there is one little catch that is not very known:

You need to have enough free space on physical disk containing VHD that it can contain whole VHD IF IT WOULD GROW TO MAXIMUM DECLARED SIZE! So 100GB VHD on a 90GB free space is a no-go, it does not matter that Windows 8 will use only about 11GB after clean installation.

Windows 8 setup does not check for this, so you may be able to install it, and not able to boot it :)

Gdje to mi živimo?

 

Vrlo naivno pitanje, na prvi pogled, koje na ovome mjestu, gdje živimo, očigledno niko ne shvaća ozbiljno. Čuje se ponegdje da smo zemlja apsurda, ali oni čiji su glasovi najglasniji kažu da smo mi u Evropi, pa čak i da smo bolji od nekih drugih mjesta. Možda i jesmo? Teško je, a i vrlo neodgovorno donijeti takav sud naprečac, ali u tekstu koji slijedi ću pokušati bar malo da odredim našu poziciju u odnosu na ostatak svijeta.

Zašto?

Mnogi koji su počeli ovo čitati će se vjerovatno zapitati koji je moj motiv za pisanje ovoga teksta, i vjerovatno niko neće ispravno pretpostaviti isti. Razlog je što sam postao otac, povodom čega sam primio mnogo čestitki i želja da novi član moje porodice ima puno sreće u životu. Razmišljajući o tome, zapitao sam se i kakav to život može da očekuje jedna beba, i počeo da zapisujem stavke koje slijede. Takođe sam htio da oni koji eventualno čekaju bebu imaju poneku informaciju koja im može pomoći.

Poređenje ovoga mjesta sa “normalnim” mjestima za život

Prva stvar koju ću da uporedim je ono u šta sam najbolje upućen, a to su uslovi za život koje može imati prosječna mlada osoba (dobro, ne baš prosječna, pošto posmatram sa gledišta visokoobrazovane osobe sa poprilično dobrim zaposlenjem, a to je ovdje statistički šiljak koji popravlja prosjek). Pod normalnim ću smatrati sve ono što se manje-više podrazumijeva u zemljama u bližem okruženju.

Obrazovanje i posao

Izbor fakulteta je dobar. Ništa bolji nego u ostatku svijeta, ali ne zaostajemo previše. Moguće je, uz malo truda i mnogo novca, upisati i završiti bilo koji faks. To je otprilike sva sličnost sa ostatkom svijeta. Prosječna porodica ne može bez značajne žrtve “izškolovati” jednog studenta, a o dva ne smije ni razmišljati. Tako je i u “boljim” društvima, reći će mnogi. Jeste, ali u našem ne postoje krediti za školovanje, stipendije su neadekvatne, a studenti nemaju mogućnost da rade i poprave svoju situaciju.

Sam kvalitet obrazovanja je, pa, kakav god da je, i dalje potpuno nebitan. Odnosno jeste, svuda osim ovdje. Zašto? Završen fakultet znači početak samostalnosti – posao u roku od par mjeseci, finansijska nezavisnost, mogućnost da se živi sam, postavljaju ciljevi i odlučuje zašto se radi. To imaju mladi u svijetu. Ovdje? Pošto ne postoji nikakva strategija, niti razvojna niti neka druga, nema niti plana koliko gdje studenata se može upisati i šta će biti s njima kada završe. Stoga prosječan student uz diplomu može očekivati i par godina na birou. Za razliku od društava kojima težimo, ne postoji nikakva nadoknada od države koja vam ne može obezbijediti posao, iako će uredno naplatiti porez ukoliko ga sami pronađete. Volio bih znati postoji li neko u ministarstvu obrazovanja ko zna koliko ovo društvo košta jedan obrazovan čovjek? Siguran sam da nema, kao što sam siguran i da u prosjeku ne košta manje od 50000KM, iako je vjerovatno u pitanju i veća cifra. Šta onda znači stotinu obrazovanih ljudi na birou? 5 miliona maraka propale investicije. Nije strašno? Ne bi bilo da ne postoje hiljade a ne stotine takvih. Da li je bolje imati 150 hiljada nezaposlenih, ili 150 hiljada nezaposlenih i 150 miliona maraka koje nisu potrošene na školovanje nezaposlenih? Zašto država dopušta da stotine miliona maraka ovoga društva propadaju? Zašto ne smanji broj, ili ukine potpuno fakultete i smjerove za koje nema posla? Bar na državnom univerzitetu? Vjerovatno zato što nikoga nije ni briga za to. Onda nije ni bitno da li je diploma samo papir, ionako će vas i vaše obrazovanje dok dobijete posao pregaziti vrijeme. Uz jedan od najvećih (vjerovatno i najveći) procenat nezaposlenosti visokoobrazovanih na svijetu, ovdje je svrha fakulteta da odvlači mladima pažnju i energiju sa bitnih stvari, izmori ih i spriječi da usmjere energiju protiv društvene truleži.

Porodica i brak

Ukoliko upoznate osobu sa kojom možete da se složite oko bitnih stvari u životu, i da organizujete zajednički život tako da poželite stupiti u brak, država će vas obradovati – čak 3 dana plaćenog odmora, a ako ste obrazovani, obradovaće vas i beneficirana stopa IRB stambenog kredita. Super. Jest da ova 3 dana nisu potrebna, meni je recimo bio dovoljan i jedan, a da sam se ženio subotom, onda mi ne bi trebao ni jedan. Ali dobro su došli za selidbu. No, kad razmislim, nema razloga zašto država ne bi dala 3 danaza ženidbu kada više od pola osoba koje stupaju u brak nisu zaposlene, pa i nije neki trošak, zar ne? Ta tri dana služe samo da bi postojao još jedan apsurd – 1 dan odsustva za rođenje djeteta. Logično zar ne? A tek druga pogodnost – beneficirana kamatna stopa za stan – to je tek sjajno. Beneficirana kamatna stopa je duplo veća od stopa komercijalnih stambenih kredita u Evropi, ali šta očekivati kada su sve banke prodane inostranim vlasnicima? Neće na svojim građanima zarađivati, jer oni imaju državu koja se brine za svoje građane. No, ni ta kamatna stopa nije bitna, jer ni uz platu koja je deset puta veća od prosječne, (ako je nemate vidite da vam ni ne treba, a ako ste zaposleni onda vam bračni drug ne radi pa vam se i to malo kreditne sposobnosti umanji) ne možete dobiti ovaj kredit, ukoliko nemate drugu nekretninu da stavite pod hipoteku. A da bi uopšte mogli dobiti kredit ne smijete je imati. Apsurd? Ma kakvi, može i žirant umjesto hipoteke. Bračni drug? Da ali u prosječnoj porodici radi manje od jednog člana domaćinstva. Recimo da imate 14 baš dobrih prijatelja (puno više nego što imate, ali optimista sam), koji bi bili voljni da vam budu žiranti. 7 ne može jer su nezaposleni. Od ovih ostalih 7 što rade, 1 ne može jer je već bio žirant i sada plaća tuđi kredit, dvojica ne mogu jer su bili žiranti previše puta i neki od kredita se neredovno otplaćjuju. Od preostale četvorice dvojica imaju dovoljno visoku platu da zadovolje kriterije banke, ali jedan već ima stambeni kredit pa ne može a drugi ne radi u državnoj firmi. Da, banke traže žiranta iz državne firme. Zna se da je ovdje država parazit a ne faktor koji obezbjeđuje dobru poslovnu atmosferu, i da će privreda propasti nauštrb države, a banke ne žele da budu na gubitku zbog toga. Tako se dođe do situacije da ja živim u stanu koji iznajmljujem. A najam plaćam manje-više koliko bi bila rata za takav stan u normalnom društvu.

Zdravstveno osiguranje i djeca

Zdravstveno osiguranje? Naravno, imam ga, i molim boga da mi ne zatreba, jer ako mi zatreba neće mi biti od prevelike pomoći, o čemu sam već pisao. Mnogo bolje bih mogao da iskoristim novac koji mi država otima od zarade nego da se “liječim” u državnoj “bolnici”, koja ima najsavremeniju opremu u Evropi na odjelu radiologije, koja košta kao flota autobusa koji ne čade, ali se ne koristi nešto mnogo, nema dovoljno obučenog kadra, uputnice se kradu a pregledi ne obavljaju, a ni mnogi građani ne znaju za postojanje ovako opremljenog centra. Ista ta bolnica nema pelena za umotavanje novorođenčadi, porodilje po nekoliko dana leže na krvavoj posteljini, a vikendom nema dežurnog doktora, pa dijete rođeno u petak naveče do ponedeljka ujutro ima dovoljno vremena da razvije razne infekcije. Ukoliko neka žena ima tu nesreću da zatrudni u ovome društvu (naglašavam ovo, jer je samo taj drugi dio nesreća), vrlo vjerovatno će imati prednost u svim redovima gdje se nešto čeka. To je sličnost sa ostatkom svijeta. Osim toga će dobiti otkaz ako je imala posao, država joj neće platiti nadoknade za trudničko bolovanje, sama će platiti školu za trudnice i imat će jedinstveno iskustvo porođaja. Naime, kod nas imaju u bolnici jedinstvene spavaćice – takve možete vidjeti samo u kaubojskim filmovima, kada se neki glumac skine u “pidžamu”, oni poparani dronjci tako izgledaju. Takođe, naši su doktori čuli za neki tamo drip. Izolovali farmaceuti aktivnu supstancu, koja izaziva i pojačava porođajne bolove. Čuli oni da se to daje tamo u Evropi, trudnicama na porođaju. Cijene oni mnogo prirodu i prirodni porođaj, ali cijene mnogo više tu Evropu i evropske vrijednosti, ipak su oni društvena elita koja treba da nam donese te novosti. Jedino što ne mogu da obezbijede i druge stvari iz Evrope, koje nisu u njihovoj moći, kao npr. bolničke papuče koje treba donijeti od kuće, ili “pamperse” za bebe, ali zato mogu da dadnu dripa desetine puta više nego što ga imaju u Evropi, nema isključivanja nakon prvog sata kao tamo, tako da time nadoknade sve što oni imaju a mi nemamo. To se dešava svim trudnicama, a ne samo mojoj. To je jedini kriterij po kome nema nikakve diskriminacije, ni po kakvom osnovu. Zahvaljujući tome prirodan porođaj postaje neprirodan kada od te supstance nateknu mišići koji treba da donesu dijete na svijet i tako mu onemoguće izlaz. Iako je u tom momentu i sestrama bilo jasno da je porođaj nemoguć, doktor je htio moju trudnicu ostaviti još par sati, ne bili se nekim čudom ipak porodila. Srećom, ona nije prosječna trudnica koja poštuje princip “ćuti i trpi” koji vrijedi za prosječnog člana našeg društva, nego je “izgubila strpljenje” kako kaže babica Mira, pa su je morali poroditi na carski rez, “samo” 5 sati nakon što su joj izazvali bolove i probili vodenjak. A babica Mira je osoba koja se samo zove babica, njeno radno mjesto se zove “uzimač mita”, jer ona ne porađa, bar je se moja žena ne sjeća. To joj nije smetalo da nakon porođaja izađe i pružajući ruku kaže “ja sam babica Mira, ja sam porodila vaše dijete, sve je u redu”. Ukoliko joj pružite ruku neće se nasmijati i čestitati nego se smrknuti i poći nazad. A kad vam doveze dijete da ga vidite, što joj je posao, još jednom će ponoviti isto. Reći će vam i da ne prima nikakvo milošte, ukoliko na njemu nije naslikan Jovan Dučić (ne tim riječima ali bit će vam jasno), a ako ga dobije umjesto zatvaranja vrata pred nosom ljubazno će vam odgovoriti na pitanja koja imate i objasniti vam gdje ćete, i kada, moći vidjeti novopečenu mamicu. Zbog pet sati porođajnih muka koje su prethodile njihovom genijalnom zaključku da je potreban carski rez, bio sam toliko bijesan da je i Mira vidjela da se tresem i pokušala da objasni da nisu oni krivi, ali doktor se, vjerovatno za svaki slučaj, ipak nije pojavio. Vjerovatno zato što on i nije planirao još da radi porođaj, ali je moja ženica “izgubila strpljenje” i počela ustajati sa kreveta, galamiti, grebati doktore koji priđu i uopšte biti nemoguća čime ih je prisilila da urade ono što su, prema njihovim riječima, “već znali da mora da se učini”. Ne znam mu ni ime, tom doktoru, čini mi se Đukić, ali ne bih htio da stanem iza toga i oklevetam pogrešnu osobu, jer vjerujem/čuo sam da ima među njima i neki dobar doktor/doktorica, koji bi mnogo bolje obavljali posao da nemaju iznad sebe takvog, koji dođe porodilji koji dan kasnije i pokuša objasniti otoke i infekcije namučenog novorođenčeta uzrocima kao što su plodova voda, infekcija majke i sl. Nakon što ona spomene činjenicu da je kontrolisala te parametre i da je sve bilo u redu 3 dana prije poroda, on kaže pa dobro, ja sam taj i taj, ako sve bude u redu recite svima da sam vas ja porodio, a ako ne bude nemojte me spominjati. Pa sjajno, to je baš sjajno. Ja volim preuzeti zasluge a nemati odgovornost za eventualne posljedice. Iako mi žena kaže da nije tako zvučao i izgledao, nadam se da se šalio, jer smo i bez toga propali. Prema tome, i prema strašnoj, žalosnoj i nedopustivoj činjenici da je dan nakon poroda moje žene umrlo dijete nakon što su ženu porađali 12 sati, su ostale gluposti, poput one da trudnice ne smiju preći vrata iz “svog” u hodnik posjetilaca i obrnuto, nego svi moraju da se nabiju u što manji prostor na vratima ne bili lakše razmijenili bakterije i viruse, naprosto zanemarive i suvišne za spominjati, ali ja ću ipak to da učinim. Da pojasnim, posjeta porodiljama izgleda otprilike ovako: ulaz u odjel su dvokrilna vrata, na kojima se otvara veće krilo, širine oko 1m. Sa jedne strane vrata tu dođe desetak nesretnica – porodilja, a sa druge dvadesetak posjetilaca, i svako pokušava da malo bude sa svojom porodiljom. Samo radi poređenja, u Sloveniji muž može biti prisutan na porođaju, doći kod porodilje u sobu i biti s njom 2 sata dnevno, i dobiti 15 dana plaćenog odsustva, a kod nas ništa od toga. Tamo porodilja ne mora nositi od kuće spavaćice, papuče, čiste peškire kojima će prekriti jastuk i na koje će staviti dijete, jednokratne gaćice, hranu (doručak je jedna viršla i četvrtina čaše mlijeka), pelene za dijete… ne mora nositi ništa. Kod nas porodilište najviše liči na zatvor. Jedine svijetle tačke su sestre, bar većina, koje i pored svih teških uslova čine sve što je u njihovoj moći da to iskustvo bude manje traumatično. Ipak se nadam da moja žena nikada više neće posjetiti ovo porodilište. Neko drugo da, ali ne ovo. Svakoj trudnici je bolje da se porodi kod kuće nego gore. Mislim da će ove slike iz porodilišta da pomognu ilustrovati kako izgleda boravak gore:

Razumijem da stanje može da bude lošije nego što bi trebalo biti, jer se planira preseljenje u novu zgradu, nekada jednom kada ona bude gotova. Ali da li je to razlog da čistačice ne očiste kupatilo, ne izvade skakavce iz svjetla iznad kreveta i ne ubace vrećicu u kantu za smeće? I da se ne može popraviti česma iz koje non-stop curi voda, i to topla! Pa čemu onda zabrana ulaza na odjel za posjetioce, svakome je čistije kod kuće, ili odakle je već došao, i sigurno je da je manje vjerovatno da će se neko zaraziti ako svako bude kod svoje porodilje nego svi na jednom mjestu, gdje ako dođe jedan zaražen ima da zarazi i sve trudnice (i djecu) i sve posjetioce…

U društvu u kome su ljudi zadnji u sistemu društvenih vrijednosti ne može da postoji stabilna država, jer bez ljudi nema ni države. Ostajanjem ovdje i plaćanjem poreza i doprinosa samo podržavamo ovakvo stanje. Ne želim nikoga da uvrijedim, ali od sada ću mislim da je glup svako kome se pruži ikakva prilika da napusti ovo mjesto, a on odluči da ostane, jer je nemoguće očekivati da se nešto može promijeniti u društvu u kome prosječan posjetilac bolnice ne zna čak ni lift pozvati u smjeru u kom želi ići. I ne samo što ne zna pozvati lift, nego ubijeđen da sve zna ne želi dok čeka pročitati uputstvo za upotrebu… Od dva zvona na ulazu na odjel, na kojima na jednom piše “Zvono za žene” a na drugom “Zvono za bebe – otpust”, dođe lik sa nosiljkom za bebu, u 12h kad je otpust, i zvoni 4 puta na zvono za žene, a onda počne da komentariše kako “nema nigdje nikoga”… Pa uzalud je ovdje pisati uputstva, kućni red, upozorenja, uzalud i ja pišem ovo, to može pomoći u društvu u kom ljudi čitaju, znaju da ne znaju i žele da nauče nešto.

Srećom, sada više nemam članova porodice u bolnici, i imam par godina do polaska prinove u školu, period u kome mogu čak i ovdje da  omogućim svome djetetu djetinjstvo približno onakvo kakvo imaju i normalna djeca, iako u ovoj “državi” nema dječijeg dodatka. A nakon toga – ponovo jedna državna ustanova. A kakva “država” takva i “škola”. Čitav svijet je u 2011. godini a naše su škole još u 1980. Ne uči se kod nas ništa što se desilo posle toga, a ne uči se ni voziti bicikl, skijati, plivati, pjevati niti išta što se uči van škole. Ovdje je to bukvalno, kada djeca idu u školu, ona idu u onu zgradu na kojoj piše škola, i to se misli pod pojmom “ide u školu”. Da stanje neće biti bolje može se vidjeti i na vijestima, kažu smanjuje se budžet za prosvjetu, ukida se x područnih škola, zbrinjavaju se radnici, ide se u propast… Samo se u skupštini, vladi i javnoj upravi ne smanjuju plate i ne zbrinjavaju radnici.

Nakon što sam sagledao ove činjenice, shvatio sam da ni jedno dijete ovdje ne može imati djetinjstvo dostojno djeteta, kao što ni građani nemaju život dostojan čovjeka, i zaključio da to zavisi od društva u kome odrasta u tolikoj mjeri da za to nije moguće napraviti kompenzaciju nikakvim drugim sredstvima. Zato se nadam svojoj prilici da mi vidite leđa…

Unobtrusive attachment of functions to events in jQuery

 

Lets say I have text input field that is part of search form, and when user clicks on find, it gets results in another part of screen. What I want is, when user changes value in some of the inputs of search form, that search results be invalidated/removed as they are not actual anymore.

As search form can have many fields, I decided to make one function for resetting search, and to make unobtrusive attachment for “change” event. I did that by adding “change” attribute to input field:

<input name="Search.SomeValue" class="valid" id="Search_SomeValue" change="resetSearch" type="text" />

This attribute is consumed by this function:

$("[change]").each(function(){
        var functionName = $(this).attr("change");
        var change = window[functionName];
        $(this).change(change);
    });

What this code does is:

- For each element with change=”something”, read something (in this case “resetSearch”) into functionName variable

- Read function from window object. Window object contains all globally defined functions

- Set this function to execute on every change of input field

 

Deserialize form from JSON data using jQuery

Recently, I got task to make feature which will make possible for user to update form data based on some unique “search” field (like VIN or SSN). I wanted to make this short and simple, and above all reusable. So, I made some investigation this weekend and came up with simple solution to use same model object that is used as type of view in asp.net mvc. It is simple javascript function:

 

var formPrefix = 'myFormPrefix';
$('sometextbox').change(function () {
 var myValue = $(this).val()
 $.ajax({ type: 'POST',
  url: 'ajaxcontroller/getcarbysomething',
  data: { something: myValue },
  success: function (data) {
  if (data){
   $("input[name*='" + formPrefix +"'],select[name*='" + formPrefix + "']").each(function () {
    var itemName = $(this).attr("name");
    var prop = itemName.substring(itemName.indexOf(formPrefix) + formPrefix.length);
    var itemValue = data.person[prop];
    if (itemValue && itemValue.substring &&
      itemValue.substring(0, 1) == "/" &&
      itemValue.substring(itemValue.length - 1) == "/") {
         itemValue = "new" + itemValue.substring(1, itemValue.length - 1);
         itemValue = eval(itemValue);
         $(this).datepicker("setDate", eval(itemValue));
    }
    else if (itemValue) {
     $(this).val(itemValue);
    }
   });
 
   }
  }
 });
});

So, to use this you need to make controller action that returns JsonResult and Json(model) instead of View(model). If form is partial view (preffered) or has explicit prefix, formPrefix is place to set it. Each form input element’s name is used to index json object returned from controller and value (if any) is set back into input element.

Autocompleting cascading dropdowns

 

Starting point for this post is source code for last one, available on bitbucket.

I want to replace dropdown list with jQuery autocomplete, like in this example. There are two reasons for this:

  • When there is very large number of records to choose from, then standard dropdown list is not very user friendly
  • When user is entering name of item, besides autocompleting from known items, we can implement addition of new item if item user needs to enter is not present in codebook. This will be done in next post.

For start, I will copy example from jQuery demo, and add textbox in which I will implement this functionality.

image

I have added this code to Index.chtml, which is label for manufacturer, hidden field with id for chosen value from dropdown, and textbox for autocomplete. I have added three attributes for this textbox:
- autocomplete-for is target (hidden field) into which I want to place chosen value
- from-url is address where I will get items for autocomplete
- parent is field for cascading functionality (this will be optional)

Client side code for autocomplete is based on jsonp example from jQuery ui demo:

image

I have added this init function to document ready event. What is happening here is simple: for each input element that has “autocomplete-for” attribute, jQuery autocomplete is added, with custom function as data provider. This function is using ajax to request data for dropdown from from-url specified in view. Parameters are MaxItems (amount of items to show in autocomplete), ParentFilterId (selected value of parent field – for cascading support) and NameStartsWith, which is text entered into dropdown which is autocompleted.

Success function maps “items” collection in response to label, value and id. label and value are automatically used by autocomplete plugin to show label for item in dropdown and to set textbox value when item is selected, and I added id to set hidden field in select event.

To make this work, there is one thing left: controller action which will return items. As you can see in first screenshot, I decided to use Manufacturer controller and action named Autocomplete.

To make parameter passing easier, I have created model for data passed in request:

image

I will receive this object as parameter in my action.

This is how implementation of autocomplete action looks:

image

This is fairly simple – query is filtered by name for NameStartsWith parameter, and I used ToLower method of string, to compare case insensitive, as StartsWith with string comparison options parameter is not supported in linq to entities.

If request contains parent filter id or max items number, then these are taken into account, and response is formed as collection of items with Text, Value and Id properties, which are used in success function of ajax request.

Time to see how it works:

imageimageimage

As this is working nicely, time for little makeup, as I want this more reusable, and not having to remember html attributes that need to be used. So, that smells like html helper:

image

Actually, it is two helpers – one for cascading case, and one for “normal”. It is the same code as in cshtml view, but creating hidden and text field in one method, and when I add comments here (removed to make screenshot smaller), I will have nice intellisense to use this function whenever I need, only having to copy and adjust controller action, which also can be made pretty generic.

 

image

This is how autocomplete is used now. I’m ready to call this a day, and source code from this post is in this changeset on bitbucket.

ASP.NET MVC3 app (part 3) – ajax cascading dropdown–unobtrusive version

 

In part 2, I made cascading dropdowns by calling selectFromAjax javascript function from my view:

image

This function has 3 arguments: address of service which provides data based on second argument – formData (in this case only id of selected item in current dropdown), and target – select list into which items from service are injected, replacing its current contents. These three parameters are almost enough to know that there is dependency between two dropdowns. Why almost? Because there is one implicit parameter – this function is part of “change” event of another dropdown – source of this event. So, source dropdown is fourth parameter. That four things are everything that client needs to know to be able to implement intended behavior of UI.

I will make this functionality unobtrusive by placing necessary information into target dropdown. Why? Because it seems most straightforward and “unobtrusive” to me, that dropdown list says “My contents depend on item selected in dropdown list X, and you need to call service Y to find out what should I show”. It is not ok to have information about MY behavior in some other dropdown X Smile. Besides, with this approach, I’m eliminating one parameter, as I have only two now: dropdown X and service Y. Third was value of dropdown X, and fourth is target dropdown itself, into which I’m adding these attributes. Value of dropdown X I can read if I know which is dropdown X, so this parameter for function anyway must be determined at the moment of changing value in X.

So, if I make my select look like

image 

then my dropdown contains all information needed to remove script from view, and place it in global js file, or make jQuery plugin. To make this information automatically embedded into my dropdown, I need to make html helper for this. If wee look at first overload of DropDownListFor in System.Web.Mvc.Html.SelectExtensions, we can easily see how new method should look:

image

My html helper will have another two arguments – depends on and load from:

image

It is using DropDownListFor helper from Microsoft, and I won’t render my own html code (and so make more space for bugs Smile).

So, view from part 2 should now look like this:

image

and generated html is:

<select cascading-dependson="ProductType" cascading-loadfrom="/Home/Manufacturers" id="Manufacturer" name="Manufacturer"></select>

Now, all that is left, is to automatically attach event handler onto “master” dropdown. It is easy using jQuery:

imageThis is adding initializeCascader to list of functions that are run on document load. This function goes through each select that has cascading attributes and attaches onchange event to element with id in cascading-depenson attribute, with self as a target for selectFromAjax function (from part 2), and value of cascading-loadfrom attribute as a url.

This is very simple concept, but can be used for chaining random number of dropdowns, and can easily be expanded to make dropdown values dependent not only on “master” dropdown, but to depend on whole form. Further improvement of this could be custom data annotation attribute, which could be used for decorating property of model, so html helper does not have to be explicitly called.

Source code for this post can be downloaded here.

UPDATE: I have uploaded source code to bitbucket.

Back to part 2