ASP.NET SiteMapPath: Nezobrazuje se vůbec, nebo jen tzv. SkipLink

Microsoft® .NET™ logoŘešení tohoto problému se na webu nikde přímo nenachází, takže opět snad někomu pomůžu. S ASP.NET WebForms jsem nikdy přímo nepracoval, takže jsem nedávno udělal začátečnickou „chybu“, o které se nikde nepíše.

Problém

Prvek SiteMapPath se ve výsledné HTML stránce vykresluje prázdný, tzn. obsahuje nanejvýš tzv. SkipLink (prostředek pro čtečky obrazovek k přeskakování „breadcrumb“ menu).

Možná příčina

Pomineme-li běžné příčiny, může to být způsobeno také tím, že soubor Web.sitemap obsahuje tzv. platformně nezávislé cesty. Tedy jen „http://server/cesta/“ a ne „http://server/cesta/default.aspx“.

Řešení

  • buď používat „ošklivé“ plné cesty včetně názvů souborů;
  • nebo použít doplněk ScionSiteMapProvider.

Tento provider umožňuje používat čisté a krátké adresy a má i několik dalších výhod.

Jak nepřijít o MVC 2 ModelMetadata atributy při práci s Entity Frameworkem

Microsoft® .NET™ logoNa webu se nachází drobná zmínka, jak tento problém vyřešit/obejít, je to ale opravdu schované.

Problém

Při psaní ASP.NET MVC 2 aplikace je možné v datové vrstvě (modelu) nastavovat atributy jako jsou user-friendly popisné názvy vlastností ([DisplayName(“Nějaký hodně dlouhý název pro nějakou Int32 hodnotu”)]), validační hlášky (např. [Required]), skrývání ([HiddenInput]) apod.

Tyto atributy se zapisují přímo do tříd datového modelu. A to znamená problém, pokud se datový model generuje pomocí Entity Frameworku (s pomocí jeho vizuálního editoru). Uživatel si sice může do code-behind tříd vepisovat atributy, nicméně po téměř každé drobné změně modelu s pomocí vizuálního editoru se znovu vygenerují code-behind třídy. A samozřejmě už bez ručně zadaných atributů.

Řešení/solutionŘešení

Žádné zcela elegantní řešení, jak zakázat Entity Frameworku přepis atributů, neexistuje. V úvahu přichází vytvořit si wrapper třídy, ve kterých otrocky přepíšeme všechny entity i všechny jejich vnitřní vlastnosti (vlastnostem přidáme atributy), a potom v aplikaci pracovat s těmito wrapper třídami. Uff.

Naštěstí existuje jakési polo-elegantní řešení. Vytvořit si v jmenném prostoru modelu zcela prázdné partial třídy se jmény původních entit, opatřit je atributem [MetadataType(typeof(NejakaEntitaMetadata))]. Dále je potřeba vytvořit odpovídající třídy NejakaEntitaMetadata, a v nich (bohužel) otrocky převyprávět ty vlastnosti, které mají mít u sebe nějaké atributy.

Díky tomuto polo-řešení alespoň není potřeba v aplikaci pracovat s nějakými wrapper třídami. Dále je možné používat původní entity, tentokrát i s atributy, ovšem už bez ohledu na Entity Framework a generovaný kód.

How to keep MVC 2 ModelMetadata attributes with Entity Framework

There is a slight mention of this problem in the web but it is really underhand.

The Problem

When writing an ASP.NET MVC 2 application it’s possible to furnish data entitites in the data access layer with ModelMetadata attributes. These can be some user-friendly descriptions of properties ([DisplayName(“Some really long caption for some Int32 value”)]), validation alerts (like [Required]), property hiding ([HiddenInput]) and so on.

These attributes should be written down directly to data model classes. And this causes a serious problem in case the model is being generated by Entity Framework’s visual editor. Although the user can write his attributes to the EF code-behind classes, these attributes get lost after even a single change has been made within the visual editor.

Solution

Unfortunately there is no elegant way of forbidding the Entity Framework to overwrite hand-coded attributes. You can create wrapper classes that incorporate all entities with all their properties, but you would have to work with these wrapper classes in the application instead of those original ones. Ugh.

Luckily you can use this semi-elegant workaround. Just create partial classes on top of those original entity classes in the model’s namespace. Then, equip them with [MetadataType(typeof(SomeEntityMetadata))] attributes. Create corresponding SomeEntityMetadata classes, declare properties that you would like to have attributes.

Thanks to this semi-elegant-workaround you are still able to work with original entity classes in your application. And your entities will have attributes set no matter what happens in the EF.

V rychlosti: Chyba v dovozování typů (type inference) v pohledech (views) v ASP.NET MVC 2

Microsoft® .NET™ logoV ASP.NET MVC 2 je drobná nezdokumentovaná chyba. Pokud se v pohledu (view) nachází několik typově silných HTML helper metod, může se stát, že kompilátor nedokáže rozpoznat typy parametrů u všech těchto metod.

Pokud pohled obsahuje vyhledávací formulář s několika typově silnými rozbalovacími menu (Html.DropDownListFor), stane se díky této chybě to, že odpovídající property ve vyhledávacím controlleru bude null.

Původní zápis

Pokud kompilátor není schopen odvodit typ parametru, měl by už při psaní kódu správně hlásit toto:

„The type arguments for method … cannot be inferred from the usage. Try specifying the type arguments explicitly.”

Nic takového ale uživatel neuvidí. Nanejvýš se dozví o obecné chybě v LINQ výrazu vyhledávacího controlleru.

Řešení

Chyba se dá obejít tak, že sami v zápisu helper metody ručně určíme typ modelu i typ property. Kompilátor se v takovém případě nesnaží odvodit typy z lambda výrazu a nemá tedy co pokazit.

Vylepšený zápis

Quick shot: Error in type inference in ASP.NET MVC 2 views

There is an undocumented error in ASP.NET MVC 2. In case there is more than just a few type safe HTML helper methods in the view, the compiler may cease to infer these method’s parameters types correctly.

Example: A search form with several strong drop down menus (Html.DropDownListFor) will not function because the corresponding property in the search controller will be null. (See the first picture above.)

In normal circumstances the compiler should give a following error:

„The type arguments for method … cannot be inferred from the usage. Try specifying the type arguments explicitly.”

But the user will not see anything like this. Most probably a generic LINQ expression error will pop up.

Workaround

You can avoid this erratic behavior by explicitly stating type parameters in those helper methods. (See the second picture.)

Follow

Get every new post delivered to your Inbox.

Join 26 other followers