A function returns only one view.
what if I want to return multiple views in a function?
For example, I have this code:
Function Index() As ActionResult
Dim _news As DataTable = News.newsSelect()
Dim _announcement As DataTable = Announcement.SelectAnnouncement()
Return View()
End Function
I want to return _news and _announcement to be used in the aspx page. How would I do this?
Are you trying to show both sets at the same time? News and Announcements?
If so then why not implement either a PartialView or two PartialViews?
Then in your main view you can render them and pass the collection to the PartialViews?
There are heaps of samples on this and the one I recommend is in NerdDinner if you haven't already seen it.
I hope this helps. If you want sample code then let me know.
One simple way is just to have those two datasets sent in a ViewData element, which you can access in a field.
example:
ViewData["Elements"] = new SelectList(aElements, "Guid", "Name");
is consumed as:
<%= Html.DropDownList("Elements","Pick an element")%>
Also, I think that if you read between the lines of this blog post here you will find an elegant way of achieving what you want ;) but its a bit more involved..(only because you mentioned Views instead of just variables..
Quote:
We need to create our own implementation of IViewFactory. This
is responsible for locating and
creating an instance of an IView
(which both ViewPage and
ViewUserControl implement).
To “inject” (all you DI fans excuse me borrowing the term without
using a DI framework) our new View
Factory into every Controller we are
going to create our own
IControllerFactory implementation.
We need to configure the framework to use our new Controller
Factory.
Finally we can create two Views – an AJAX version and a pure
HTML version.
Building on that should be all you need
Good luck!
Ric
Assuming what you are trying to do is use both of those DataTables to populate some View, then my recommendation would be to create a wrapper object and then a strongly typed view based on this object.
The wrapper object would contain properties for all of the data elements that you need in order to render your view properly. In your case, it is 2 DataTable objects. I do not really know VB, so all my examples will be in C#. Here is an example of the data wrapper class...
public class IndexViewData
{
public DataTable News { get; set; }
public DataTable Announcement { get; set; }
}
You then might update the Index action in your controller as follows:
public ActionResult Index()
{
var viewData = new IndexViewData();
viewData.News = News.newsSelect();
viewData.Announcement = Announcement.SelectAnouncement();
return View(viewData);
}
Finally, you would need to create/update your view to be strongly typed. This is done by having your page inherit from the generic System.Web.Mvc.ViewPage<T> class. Just substitute the view data wrapper created earlier for T. To do this, you would set the inherits attribute of the <%# Page %> element. In your case, if we assume your root namespace is called "Foo", you might have the following page declaration in your Index.aspx view (added extra line breaks for readability):
<%# Page Title=""
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<Foo.Models.MyModelType.IndexViewData>"
%>
Once you have a strongly typed view for your view data wrapper, you can access the wrapper object in your view using the Model property. Here is an example of something you could do in your Index.aspx view
<%-- Output some random data (bad example, for demonstration only) --%>
<%= Model.News[0]["title"] %><br/>
<%= Model.Anouncement[0]["body"] %>
In reality you're probably going to do something like iterate over each row of the data table. Regardless, once you create the strongly typed view, your model object, which was passed to the view in the Index method of the controller, is available in the Model property within the view.
You can find detailed tutorials at the ASP.NET MVC site
Related
I have one page that will contain a lot data.
Outline of the page is on the image.
For output I have used "razor" engine.
Now I wonder will I get something if I refactor my code so each section
which data comes from database will be partial view?
On this page I need about 20 value objects to display all needed data.
I have made one "ViewModel" class that contains all data I need and set that
viewModel class as razor page model. Is this the right way how I should do this or
there is some smarter way?
public class MyViewModelClass{
public ValueObjectx x;
public ValueObjecty y;
public ValueObjectz z;
public List<ValueObjectT> tList;
public List<ValueObjectG> gList;
public List<ValueObjectS> sList;
}
In a scenario like this I would typically have each section as a partial view. Each section is responsible for it's own layout and ViewModel. This prevents the tendency to have a super view which has to know about too many things in order to render.
I would not use one ViewModel for all the data. I would only use the ViewModel for the data that might actually be posted back to the server. For all the other data, like lists, I would put it on the ViewBag. Like:
public ViewResult SomeAction()
{
var model = GetYourModelData();
ViewBag.TList = GetTList();
ViewBag.GList = GetGList();
ViewBag.SList = SList();
return View(model);
}
You could put all the lists in a separate helper object if you use them a lot.
Note that this is not a "this is how you should do it answer", it is more a description of what works for me. But as I see it the model of the view is one thing and the actual data, as data in drop downs etc., on the view is another thing and should be put in the ViewData property, but the ViewBag is just a dynamic wrapper around the ViewData property. You can then use the properties on the ViewBag as input to your partial views that should make up each of your sections.
I've a problem with Partial View.
I am developing a blog in asp.net mvc and I would make in my masterpage a list of categories, last post, last comments.
I think that the best solution is to use strongly typed partial view, and in each partial view pass the necessary model.
MY problem is that the model in View.. in any view (connected to the masterpage's contentplaceholder) enter in conflict with the models in partial views and I get an error like this:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[Blog.Models.Articoli]' but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Blog.Models.Categorie]'.
I found on web a dirty solution that consist of to pass togheter the model of any view, some viewdata, one for every model to pass in partial view. But this solution don't respect DRY Principle..because you must repeat this code for each action!
So, my question is: Can I create a model that contain also partial view's model?
If, yes, in that way?
It Exist another solution more simple?
Thanks for help
How about the View Model Pattern?
I've created wrapper classes that are passed to my views rather than whatever object I would normally use
public class MyCreateUserView
{
public User CreatingUser { get; set; }
public MyPartialViewObject Blah { get; set; }
}
In your view write:
public ActionResult CreateUser()
{
MyCreateUserView createUser = new MyCreateUserView()
{
CreatingUser = GetUserFromSomewhere(),
Blah = GetPartialViewObject();
}
return View(createUser);
}
Then your page header looks like so:
<%# Page Language="C#" Inherits="ViewPage<MyCreateUserView>" %>
and when you render your partial write:
<% Html.RenderPartial("../MyPartialViewObject ", Model.Blah); %>
Instead of solving that with the pattern you describe (which is generally a great pattern), I solve that with calls to RenderAction and have it return a partial view. That way the code is in one place as each call to each view does not have to worry about marshalling all the data you need. If you want to see a short discussion on how to use it, I would check Haack's blog here: http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx. You can also check out the discussion on this other post here on SO: ASP.NET MVC Master Page Data
I have a page for creation of dynamic entities.
<%# Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
...
I have two actions:
public ActionResult Create()
{
dynamic model = ...
return View(model);
}
[HttpPost]
public ActionResult Create(dynamic(1) entity)
{
...
}
Well, the problem is that the entity comes empty from the page. If I change dynamic in (1) for the real type it works fine.
I'm not 100% on this, but I think the problem is that the default model binder has no idea what to do with a 'dynamic' type, since it doesn't have any defined properties to reflect over. You'd need to write your own model binder that would use the form input names instead, which is dangerous/unreliable because the form can be modified on the client side.
I've explored dynamically-typed ViewPages before (here on SO actually: Dynamic typed ViewPage), and I've come to the conclusion that it really doesn't give you anything in most situations. At least, not yet (MVC 3+ could be different story).
And here's some notes from Phil Haack on the matter: http://haacked.com/archive/2009/08/26/method-missing-csharp-4.aspx
Sorry if this is a basic question - I'm having some trouble making the mental transition to ASP.NET MVC from the page framework.
In the page framework, I often use ASCX files to create small, encapsulated chunks of functionality which get inclded in various places throughout a site. If I'm building a page and I need one of these controls - I just add a reference and everything just works.
As far as I can tell, in MVC, the ASCX file is just a partial view. Does this mean that wherever I want to add one of these units of functionality I also have to add some code to the controller's action method to make sure the relevant ViewData is available to the ASCX?
If this is the case, it seems like a bit of a step backwards to me. It means, for example, that I couldn't just 'drop' a control into a master page without having to add code to every controller whose views use that master page!
I suspect I'm missing something - any help would be appreciated.
Thanks,
- Chris
As far as I can tell, in MVC, the ASCX
file is just a partial view. Does this
mean that wherever I want to add one
of these units of functionality I also
have to add some code to the
controller's action method to make
sure the relevant ViewData is
available to the ASCX?
Yes.
However, you can use a RenderAction method in your view instead of RenderPartial, and all of your functionality (including the data being passed to the sub-view) will be encapsulated.
In other words, this will create a little package that incorporates a controller method, view data, and a partial view, which can be called with one line of code from within your main view.
Your question has been answered already, but just for sake of completeness, there's another option you might find attractive sometimes.
Have you seen how "controls" are masked on ASP.NET MVC? They are methods of the "HtmlHelper". If you want a textbox bound to "FirstName", for example, you can do:
<%= Html.Textbox("FirstName") %>
And you have things like that for many standard controls.
What you can do is create your own methods like that. To create your own method, you have to create an extension method on the HtmlHelper class, like this:
public static class HtmlHelperExtensions
{
public static string Bold(this HtmlHelper html, string text)
{
return "<b>" + text + "</b>\n";
}
}
Then in your view, after opening the namespace containing this class definition, you can use it like this:
<%= Html.Bold("This text will be in bold-face!") %>
Well, this is not particularly useful. But you can do very interesting things. One I use quite often is a method that takes an enumeration and created a Drop Down List with the values from this enumeration (ex: enum Gender { Male, Female }, and in the view something like Gender: <%= Html.EnumDropDown(Model.Gender) %>).
Good luck!
You can render a partial view and pass a model object to.
<% Html.RenderPartial("MyPartial", ViewData["SomeObject"]);
In your partial view (.ascx) file, you can then use the "Model" object (assuming you've inherited the proper object in your # Control deceleration) to do whatever you need to with that object.
You can, ofcourse, not pass and Model and just take the partial view's text and place it where you want it.
In your main view (.aspx file), you will need to define the proper object in the ViewData that you're passing to the partial view.
Another method you can do is use:
<% Html.RenderAction("MyAction", "MyController", new { Parameter1="Value1"}) %>
What the previous method does is call a controller Action, take its response, and place it where you called the "RenderAction()" method. Its the equivalent of running a request against a controller action and reading the response, except you place the response in another file.
Google "renderaction and renderpartial" for some more information.
I have a View strongly typed to an Item class. In my controller I need to send two different List. Is there an easier way to do this other than creating a new class with two List.
What I am ultimately trying to do is have on my homepage 10 items ordered by Date, and 10 items ordered by Popularity.
WHAT I DID
I actually went with a combination of the two answers. I strongly-typed my View to the new class I created with the two lists. I then strongly-typed two partial views to the each one of the lists. May seem like overkill, but I like how it turned out.
"creating a new class with two Lists" is the way to go. It's called a view model and once you embrace it, the power of strongly-typed views really opens up. It can be this simple:
public class IndexViewModel
{
public List<Item> Newest { get; set; }
public List<Item> Popular { get; set; }
}
There are two general philosophies to this. The first is to take the approach John Sheehan stanted. You create a custom view model with both lists and pass that to your strongly typed view.
The second is to consider the lists as "ancillary" data and put them in ViewData like jeef3 stated. But, when you render the lists, you use a strongly typed partial.
ViewData["Newest"] = Newest;
ViewData["Popular"] = Popular
By that I mean in your main view, you'd call RenderPartial(...) but pass in the view data key you used.
And your partial would look like:
<%# ViewUserControl Inherits="System.Web.Mvc.ViewUserControl<List<Item>>" %>
...
This gives you strongly typed access to that view data from within your partial.
It's what John suggested or not having a strongly typed view and adding them to the ViewData:
ViewData["Newest"] = Newest;
ViewData["Popular"] = Popular
Another option would be Strongly Typed Partial views.
You should make a model that includes both lists specifically for the view.
Typically in the little MVC I have done, I have made a model for each view even if they just passed along identically data that was served up for by data or business layer just to keep the separation between the two parts very strict. This setup is a little more work and not needed in many simple cases but it does keep things cleaner in my opinion.