Is there any way to create a ViewDataDictionary
with a model and additional properties with a single line of code. I am trying to make a RenderPartial
call to a strongly-typed view while assembling both the model and some extra display configuration properties without explicitly assembling the ViewDataDictionary across multiple lines. It seems like it would be possible given the RenderPartial
overload taking both a model object
and a ViewDataDictionary
but it looks like it simply ignores the ViewDataDictionary
whenever they are both populated.
// FAIL: This will result in ViewData being a ViewDataDictionary // where Model = MyModelObject and there are no other parameters available. this.Html.RenderPartial("SomePartialView", MyModelObject, new ViewDataDictionary(new { SomeDisplayParameter = true }));
I found someone else with the same problem, but their solution is the same multi-line concept I found: create a discrete ViewDataDictionary
with the model, add the new parameter(s) and use it in the RenderPartial
call.
var SomeViewData = new ViewDataDictionary(MyModelObject); SomeViewData.Add("SomeDisplayParameter", true); this.Html.RenderPartial("SomePartialView", SomeViewData);
I can always wrap that logic into a ChainedAdd
method that returns a duplicate dictionary with the new element added but it just seems like I am missing some way of creating a ViewDataDictionary
that would do this for me (and that is a bit more overhead than I was hoping for).
this.Html.RenderPartial("SomePartialView", new ViewDataDictionary(MyModelObject).ChainedAdd("SomeDisplayParameter", true)); public static ViewDataDictionaryExtensions { public static ViewDataDictionary ChainedAdd(this ViewDataDictionary source, string key, object value) { return source.ChainedAdd(new KeyValuePair<string,object>(key, value)); } public static ViewDataDictionary ChainedAdd(this ViewDataDictionary source, KeyValuePair<string, object> keyAndValue) { ViewDataDictionary NewDictionary = new ViewDataDictionary(source); NewDictionary.Add(keyAndValue); return NewDictionary; } }
As well, trying to assemble a ViewDataDictionary
with an explicit Model
and ModelState
simply causes a compilation error because the ModelState is read-only.
// FAIL: Compilation error this.Html.RenderPartial("SomePartialView", new ViewDataDictionary { Model = MyModelObject, ModelState = new ViewDataDictionary( new { SomeDisplayParameter = true }});
ANSWER(S): It looks like Craig and I ended up finding two separate syntaxes that will get the job done. I am definitely biased in this case, but I like the idea of setting the model first and "decorating" it afterwards.
new ViewDataDictionary(MyModelObject) { { "SomeDisplayParameter", true }, { "SomeOtherParameter", 3 }, { "SomeThirdParameter", "red" } }; new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }}) { Model = MyModelObject };
Of course, I would still be spinning my wheels without his [eventually spot-on] answer, so, circle gets the square.
ViewData itself cannot be used to send data from View to Controller and hence we need to make use of Form and Hidden Field in order to pass data from View to Controller in ASP.Net MVC Razor.
Create a hidden input <input type="hidden" name="selectedTabIndex"/> and set the value with javascript prior to POST . The controller can extract this value from the Form parameters, or it can be autopopulated in the Action method if the method contains a parameter matching the input name.
ViewData is a ViewDataDictionary object accessed through string keys. String data can be stored and used directly without the need for a cast, but you must cast other ViewData object values to specific types when you extract them.
Use an object initializer and collection initializers:
new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }}) { Model = MyModelObject }
The inner ViewDataDictionary gets its collection initialized, then this populates the "real" ViewDataDictionary using the constructor overload which takes ViewDataDictionary instead of object. Finally, the object initializer sets the model.
Then just pass the whole thing without setting MyModelObject separately:
this.Html.RenderPartial("SomePartialView", null, new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }}) { Model = MyModelObject });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With