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