Controls without views for globals functions in asp.net MVC (with razor) - asp.net-mvc

The well described model of View/Controller/Model is quite clear when it comes to object (say a book) update/delete/save etc...but how do you guys organize the common code such as populating drop down lists (from db)?
I use Jquery ajax to call control's action, but in cases such as getting the arrays for drop down lists, I feel like these should not reside in the same BookController .
Can I have a Controller without the matching view for these purposes only?
Thank you

Each ViewModel is data for a View to render. It sounds like you understand that. When Ajax calls for Data, I think it makes more sense for the controller for the view be responsible for creating another ViewModel and returning it as Json for the rendered view. If mutliple views need to retrieve a list of Books, should call /Books/AjaxList (bad method name example), just like any view under /Books. Seperating the responsibility of creating a ViewModel based on Ajax or not Ajax doesn't make sense to me.

Related

ASP.NET MVC List of Web Components in Model

I need to get dynamically a list of Web Controls from View to be used in the model(dropdownlists, inputs, checkboxes, ...). Is it possible? I generate the controls in Razor.
My application should store last values of all controls for each user into the database and use them as predefined values for the next call of the form.
Any advice would be appreciated.
I need to get dynamically a list of Web Controls from View to be used in the model
First of all, you're probably going to find MVC a lot easier to understand if you abandon terms like "web controls" and the like. Your view, which may not may not be utilizing helpers to do so, is simply building HTML. Nothing more.
But more to the point, what you're proposing is exactly the opposite of what MVC does. Your model should have no knowledge of the structure of the view. (inputs, selects, other form elements, etc.) The model contains the data and business logic necessary to render the view. The view then uses that data and logic to build its interface.
You can post the values from the resulting HTML form to a server-side action. Then from that action you can store those values in a database or do whatever you like with them. If the key/value pairs of those values can logically be structured into the form of a model then the action can accept that model as a parameter, if not then it can also just as easily accept parameters for each individual value. (Though if you find yourself using a lot of parameters it would be better to build a simple view model just to encapsulate them.)
The order of operations is something like:
A request is made to a controller action.
That controller action invokes logic on a model and provides that model to a view.
The view binds its UI elements to the model's data and renders the interface.
The user interacts with the interface and uses it to perform a request to another controller action.
That controller action receives the data from that request, performs server-side logic, etc.
and so on...

How To: Use MVC and Ajax to add / remove a row in grid for data entry + model binding?

I'm new to Ajax, but I think I know how to reasonably use MVC + model binding.
What I'm trying to do is to create an Add button (or Ajax.ActionLink) to add a new row in my grid for data entry. Example: Think of a typical Order entry system with Order (header) and Product (items). My OrderViewModel contains an "Order" object, and the Order object contains a collection List.
The way I plan to do this is that my View render the grid in a PartialView, and the PartialView is a simple for-loop to create the table tags from the List. I will use the default model binder (for collections).
Anyone have suggestions on how to do this?
I've already figured out how to do this using jQuery, but I want (i think I want) to try and use Ajax so that I can add my custom business logic (e.g. like setting defaults, translations, etc.)as opposed to do this client-side.
In other words, I want to do do something similar to what the Telerik grid does with its Ajax Editing with the Add/Remove link/buttons.
Tips and sample code would be greatly appreciated.
One of my challenges, and not sure if I'm going down the wrong way, is that I don't know how to pass back the model back to the Controller Action from the Ajax submit. When I look at Telerik's code, it looks like they store the persisted items in HttpContext.Session, and this is exactly the reason why I don't want to use their grid.
Thanks.
They might choose the session repository storage for demonstration purposes. If you transform the logic from their SessionProductRepository class for your model and implement identical Update/Insert/Delete methods for it, you'll probably get what you want.

ASP.Net MVC reusable form as RenderAction or RenderPartial

I'm looking for a best practice for embedding a form on multiple pages as a partial view.
I have a contact form I'm looking to embed on multiple pages on a site. Usually, the form would be on a contact page and the contact model could be the model for the view and use data annotations for validation. However, the view is already strongly typed.
How can I create a reusable form in a partial view and embed it on the page? I'm using N2 on the site, so the pages have to already have a strongly-typed model, but I would be open to extending those objects.
Personally, I recommend using for Html.RenderAction() for cross-cutting concerns such as these.
The handler for your contact form is going to need to exist independently of the page your are currently viewing so you are left with 3 options:
Manually add it to the response of
the current action
Manually add it to the response of
the current controller by way of a
base controller that modifies the
ViewState or ViewModel
Call the RenderAction()
HtmlHelper inside of the current view
Of these 3 options, while the third is technically more costly than 1 and 2 (because it initiates a brand new request), it is also the most maintanaible solution. By calling RenderAction() you have the advantage of being able to completely isolate your contact form from the rest of the view and thus you won't have to worry about hacking it into the current controller responses.
Use RenderPartial if data model for partial view is already in main view's model, in other case use RenderAction (then the action of the partial view will create its view model itself).

RenderPartial and Dynamic Selection of Partial Views

My MVC application contains a parent model, which will contain 1 or more child models.
I have set up the main view to display properties from the parent model, and then loop through a collection of my child models (of various types, but all inheriting from the same base type). Each of the child models have a corresponding partial view.
My "parent" view iterates over the child models like this:
foreach (ChildBase child in ViewData.Model.Children)
{
Html.RenderPartial("Partials/"+child.ChildType.ToString()+"Child",
section);
}
My application has the appropriate /Partials/ChildType1.ascx, ChildType2.ascx, etc. Everything works great.
Is this an appropriate way to use Partial Views? It feels slightly off-kilter due to the dynamic names, but I don't know another way to perform dynamic selection of the proper view without resorting to a big switch statement.
Is it advisable to use the same view for multiple "modes" of the same model? I would like to use the same .ascx for displaying the "read only" view of the model, as well as an edit form, based on which Controller Action is used to return the view.
Iconic,
It's difficult to answer the questions without knowing exactly what you're trying to achieve.
I'll have a go though:
If you're familiar with web forms, think of your partial view as a webforms usercontrol for the moment and think of the part of your model that is relevant to your partial views as a 'fragment of information' that want to pass across to the partial view.
Natural choices for using a partial view would be for elements used in many views across your site.
So ... in answer:
1.Although what you are doing is valid, it doesn't seem quite correct. An example of a partial view I have used might be a row in a grid of data where you'd call the partial view passing in the row object as its model:
foreach (MyObject o in Model.objects)
{
Html.RenderPartial("Shared/gridRowForObject.ascx", o, ViewData);
}
You can strongly type your views also to expect a specific type to be passed through as the Model object.
Again another use might be a login box or a 'contact me form' etc.
2._Ultimately this is a personal design decision but I'd go for the option that requires the least application/presentation logic and the cleanest code in your view. I'd tend to avoid writing to many conditional calls in your view for example and by inferring a base type to pass across to all of your partial views as in your example, may well tie you down.
When learning the MVC framework I found the Oxite code to be useful.
I hope that helps.

Rendering multiple views from multiple controllers on a single page

On the main page of my site, I would like to show several views which rely on their own controllers for data retrieval. I do not want to retrieve anything from the DAL in my Home controller.
For example, I want to show view listing top 5 news, a view with random quote from the database, another view with the users shopping cart contents, etc.
After Googling around, I found RenderAction method which is almost perfect, but it's not available in RC1, only in Futures, and apparently, it has some issues.
I found RenderPartial as well, but that relies on the main controller to pass data to the view.
Additional clarification:
The main reason I do not want data access logic in the Home controller is to avoid repeating the code and logic. I will use top 5 news view in several pages/controllers. I do not want to repeat data retrieval in every one of them. I already did separate a lot of logic and validation to business layer. The solution I'm after is RenderAction or UserControls as in classic ASP. I know i can use them in MVC as well, but... whats the point? I mean, if what i'm asking is too complicated or too absurd (reusable UI components), then MVC is definitely not for me, and I'd consider it seriously inferior to classic ASP.NET, because this requirement is really simple.
What you're asking is to basically not perform data access in the HomeController, this seems like a dogmatic approach. I would consider either using RenderAction from the Futures assembly (not sure what's wrong with it, I use it in a number of projects) or SubControllers from MvcContrib.
While I can understand the desire not to replicate functionality in multiple controllers, I don't understand the reluctance to have your Home controller interact with the DAL. I think the partial view is definitely the way to go. My solution to not replicating the functionality would be to push the code that generates the data for the various views into your business or data layer. You could then reference it from each of the required controller actions that use the partial views. Putting it in the business layer could isolate the controller from your data layer, if that's what you desire, but I still think it's the proper job of the controller action to obtain and provide the data to the view.
Another potential solution would be to populate the view generated by your Home controller via Ajax callbacks to the various controller actions that generate the required view components. The drawback to this is that it doesn't fail gracefully in the absence of javascript in the browser.
EDIT
Based on your clarification, I would suggest implementing a base controller that fills the ViewData for the shared controls in ActionExecuted (so that it's done only when the action succeeds). Derive your other controllers from the base controller when you want to inherit this behavior.
If you really don't want to use RenderAction, then the only other option you have is to load the necessary data pieces with action filters. Your home controller could then look like this:
public class HomeController : Controller
{
[RequireNews]
[RequireQuotes]
[RequireCart]
public ActionResult Index()
{
return View();
}
}
These action filters could be re-used where they are needed. You might also choose to place these on the controller class itself.

Resources