Setting ViewData item in a Partial to be read in a View - asp.net-mvc

I have a View which I call RenderPartial.
In the Partial usercontrol I set ViewData["IsTextAreaVisible"] = true;
In my View after the call to RenderPartial I check the value of ViewData["IsTextAreaVisible"].
Even though the usercontrol had set it, the View thinks that it is null.
Is this a bug or is there a better approach?
Thanks

That is working as designed.
Each partial view gets it own copy of the view data so that any changes it makes don't taint the original. What you want to do, we've expressly prohibited.

I think that the RenderPartial method actually makes a new dictionary out of the object you pass it as ViewData. Since the dictionary is different, the original won't contain any new values you've added to it.
It seems to me though, that if you can calculate the value you are setting in the partial, you ought to also be able to calculate it in the parent view. You might want to think about reversing the calculation and perform it in the parent view and add it before calling the partial. You could always check if it is available in the partial and, if not set, recalculate as needed.

Exchange of data between components of a view looks to me like a design fault. View (full or partial) are there just to passively and stupidly display the model state. All checks, calls and set up of values should be done in models/controllers. I would advice you to rethink you architecture. Even if it seems to you nice and suitable right now, there is a likelihood sooner or later you will have to redesign this piece of code.

Expanding on what Brad said, do it client side with JavaScript. Using JQuery you can find out if there are any visible textboxes on the page and init the client as so.
$(document).ready(function() {
if ($("input[#type=text]:visible").length > 0) {
// inject JS file and init tinyMCE.
$.getScript('<%= ResolveUrl("~/Scripts/tinymce/tiny_mce.js")' %>, function() {
// TODO: call tinyMCE's init function here
});
}
});
That will initialize it only if there are inputs that are visible.
See http://docs.jquery.com/Ajax/jQuery.getScript for restrictions on getScript
Edit: Edited to expand it based on Jon's comment. Note that I haven't run this revised edit in a browser so there may be a hiccup or two. Also, this should really be re-tagged with jQuery if you accept this solution.

Related

How much code is acceptable in a View?

I was wondering how much code is acceptable in a view ? It is acceptable to use foreach or if such if a list of items is empty.. show some message ? or should this be done in the controller ?
in a really few works
The View should containt all the code you need for your presentation logic even ForEach (if you need them)
Some people like to create HTML helper to split down the presentation logic and inclapsulate it into an adhoc method
The control should be very skinny: it should just get the user interaction and delegate them to the right component. It may contain some validation logic (user input etc) but it really depends by your business requirements
Rushino,
To address the specific example that you cite. For a list of items, I'd be tempted to include a strongly typed helper in the view that either returned the appropriate list OR simply returned an empty MvcString. As for other logic in the view, i'd keep it to a minimum as you quickly run out of options for unit tests once the view is littered with case statements and ifs and buts. Of course, there will be occasions where the judiciuos use of a few varables may be acceptable, but few and far between.
just my 2 cents

ASP.NET MVC - How to best build a form action that can respond in many ways?

I am in the process of writing a web app that includes a reporting form. This form contains a number of radio buttons that allow the user to specify the return data.
There are about 6 different return data 'formats', and each of those has two variations - html data or JSON data for rendering to a chart.
I have begun coding it up and already my form post action method feels wrong.
I basically have a check on the requested data format and return it as needed. Each return type requires its own partial view / json object so there is little room for reusing code.
It feels like each one should have its own action method. Having the form post to different locations based on a radio button choice also feels wrong though.
Switching on report type and then redirecting to the appropriate action in the controller also feels like its not quite right.
Am I approaching this in the wrong way? As it currently stands my controller action contains a lot of code and a lot of logic...
Hope my query makes sense.
Thanks
I don't think there is anything wrong with your approach. To maximize reuse you could:
include reusable templates inside your views
make sure the business/data layer code is the same everywhere (where possible)
I suppose the views you need to return actually are different for each combination of options so whatever approach you take, you are stuck with that.
I wouldn't opt for the client-side approach. You then have code on both the server and the client that has to be updated whenever you change anything. I would keep the code that receives a set of options and determines what to do with them in one place.
I know what you mean about it feeling like each format should be a separate action, but maybe a hybrid approach would make it feel better.
If you set the value of each radiobutton to the name of the action it relates to, you then, in your main POST action, have a parameter that you can use to call the appropriate action in one line of code. You don't have to fudge anything in Javascript, it's easily extensible, and you get your separate actions.
If I understand your problem right you have a lot of switch code in action.
I think you can use Factory pattern. You can create factory that will accept switch parameter as parameter and will return ActionResult instance.

Rendering Navigation in MVC3

What's the best way to render Navigation in MVC3? In my app the Controller has to decide what should be in the Navigation but as far as I know there's no way to pass a Model up to the _Layout file (where the Navigation html lives) to give it this information.
You can make the model available to your layout.
Define a base class, MyBaseModel, with the properties you want available to the layout.
Have your models subclass MyBaseModel, and ensure that you populate the properties
Have your layout specify #model MyBaseModel
Use the properties
See also this blog post where a similar problem ("we often find ourselves needing to include the same information in every page") is tackled.
Best is a relative and subjective term. I would usually go with an approach similar to druttka's answer but another option is to use RenderAction() to invoke a controller action
<div>#Html.RenderAction("action", "controller")</div>
I will offer some counterpoints to #druttka's answer. But mostly, you have to decide which trade off you want to make.
If you use a model for your view, you are now forcing 2 things:
Every view must be strongly typed
Every action must call the function to populate all levels of nav included in your view model
The first point isn't so bad, because there are very few pages in a typical non-static site which wouldn't derive from a model anyway, and its easy enough to create an empty model for those pages. The second point is much more annoying however. Each function has to instantiate it's own model, and then populate the nav properties for every level of nav provided by the model. This can be quite cumbersome, but can be fairly elegantly handled in OnActionExecuted for at least nav which is not specific to a given action.
The alternative is to add the nav to the ViewBag. This can be done whenever and does not force you to specify a model for every view, which is great for the flexibility in those cases where you do not need to specify a model. It should be noted however that the ViewBag in asp.net mvc 3 is of type dynamic, which you cannot use as a parameter in a lambda function, thus preventing you from doing something like #Html.DisplayFor(viewBag => viewBag.MainNav) in your layout, which is a real drag. You can still render partial and specify the appropriate DisplayTemplate however.

ASP.NET MVC 3, Razor Layout Controller-like?

Haven't found anything about how to do this. I Require some code to run to update data in my Razor Layout.
I could do this by running the code in every Action that is using the Layout and setting ViewBag data, but that seems impracticable...
So, how would i do this in a better way?
The answer to this question, proposes to use a global action filter.
That is a piece of code (filter) that is executed on every action, you can use it, to set properties in the ViewBag. These properties are accessible from every View, and from the layout.
If the data you are rendering in your layout is orthogonal to the data of your actual view (which it should be, or otherwise you are using layouts where you should be using partial views), then imho the conceptually most sound method would be to employ a child action (i.e. using Html.Action) to render the data into the layout.

Refresh several partial view

Is there a way to refresh several partial view from the controller ? (return View())
Thanks,
Update1:
Example, the content pârt of my screen is divided in 2 parts, on the left a customer list on the right the details customer, the details of the customers selected in the list of the left. If I create an new customer, when I save, I'd lile refresh the list (left part) and see the details (right part)
Kris,
the only way i can think to do this simply is by having multiple partialviews embeded within the main 'view' to be refreshed. these would then be refreshed in the same cycle. alternatively, you could have custom html helpers embedded within the main view that ran approprite code when the view was refreshed.
As for multiple views from a single action, i don't think this is both a good idea or in any way possible.
of course, rules are there to be broken :)
I don't think there is any automatic way to do this, but you could use some convention and:
Create a custom view result that takes in multiple partial view results i.e. a MultiplePartialViewResult
In the execute of the custom view result, call each the execute method of each of the supplied views'. Make sure to wrap each in a div or some other container for ease of retrieval at the client script
Upon receiving the response on the AJAX call in the client script, grab the value from each container and replace it in the corresponding elements matching the partial views initially rendered
For the last step you could use a convention. A simple one would be (if there is only one instance for each partial view) to put the id of target html element to update in the div/container you used to wrap it in the second step.
Based on what you're saying, I think using javascript and ajax to refresh from the server would be best.
You could use Html.RenderPartialAction to achieve DRY by putting it on the page, and then loading it using ajax and javascript.
If you were using jQuery, then something like this would work:
jQuery("#divToReload1").load('Url/To/PartialAction')...
jQuery("#divToReload2").load('Url/To/PartialAction')...
Just put that all inside one function and you'll reload all your partials at once.
You can send data through using the data parameter and catch the callback function to do as you wish.

Resources