ViewData not available from partial view when using TemplateFor

Jun 27, 2013 at 4:33 PM
Hi,
I'm not sure if is known behavior and I;m just not doing something correctly or if it might be a bug, but it appears that I am not able to access anything that I put into the ViewData collection from a partial view that is being processed by a call to the TemplateFor helper.

Everything about the ClientBlock setup looks to be working properly for me, so I think I have things setup correctly. In my controller however I am adding several lists to ViewData to use to populate dropdowns in the partial view. They are available in the main view that the controller calls, and it is in this view that I make a call to TemplateFor to process a partial view. The four lists and two string properties that I added are gone and only two properties exist that look to be related to the processing of client blocks.

Is there anything special I have to do so that ViewData flows through and is available to the partial view? I originally had the select lists within the viewmodel class that I'm passing to TemplateFor, but that clutters things up and I don't need all of the items in these lists getting created in the resulting client side viewmodel (knockout) object.

I can post code examples as needed, but wasn't sure what would be useful.

Thanks
Scott LeWarne
scottlewarne@gmail.com
Coordinator
Jun 28, 2013 at 8:06 AM
Edited Jun 28, 2013 at 8:12 AM
Hi Scott,
There is no Bug! In Asp.net MVC the ViewData of the main view is automatically copied into a PartialView only when the partial View uses the same ViewModel of the Main Page. In all other cases you have to copy manually the data you need in the Viewdata dictionary of the Partial View by using this overload of RenderPartial (or the analogous one of Partial).

Now when you pass the partial to the TemplateFor helper you can't pass in a new ViewDataDictionary. The main reason being that the Partial View must be set up properly to be usesd in a client Block, and passing a custom ViewDataDictionary might interfere with this set up. Other reasons are that, as I will detail at the end of post, ...this is not a good pattern.

However, you may overcome this problem by using a Razor Helper instead of a Partial View. For more details on how to use a Razor Helper as a Template for a client block see the general dicussion about templates here.
If you use a Razor Helper defined in the same Main Page you have access to the ViewData of the main page...so the problem is solved. If you want you may call a PartialView from within the Razor Helper, but this time you call manually the Partial helper so you may pass in a custom ViewDataDictionary where you may copy all data you need from the ViewData of the main View.

To finish...when using client blocks it is good practice to put everything you need on the client side in the client ViewModel. In your case if you don't put your list in the client model, all select list items will be rendered immediately in the Client Template that is being created with TemplateFor. In other terms they will be rendered on the server side. On the contrary if you put your list in the Client Model the select list will be created dynamically using the data contained in the client ViewModel, when the template is istantiated on the client side. Now since data in the ViewModel require less bytes than the Html of the select list items the second solution result in a smaller page and in higher level of flexibility. The advantage increases if the same data are used to create several select lists: if you create the select lists dynamically your page will have just ONE copy of these data...the one contained in the client side viewmodel since all select lists will be created dynamically.