I want to call a PartialView from my Index.cshtml which uses different Model that I want to call PartialView.
My Index.cshtml
#model IEnumerable<myappname.Models.Post>
...
#Html.Partial("_Block")
_Block.cshtml
#model myappname.Models.RightBlock
<img src="#Model.blockContent" width="330" />
Controller.cs
...
public PartialViewResult _Block()
{
int id = 2;
RightBlock rb0 = db.RightBlocks.Find(id);
return PartialView(rb0);
}
...
Please ignore the id because I just want to call it statically, not dynamically.
When I run the Index Page, I get an error:
The model item passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery`1[myappname.Models.Post]',
but this dictionary requires a model item of type
'myappname.Models.RightBlock'.
How can I pass different model to call PartialView?
Thank you.
Use Html.Action
Index.cshtml
#Html.Action("Block")
Controller.cs
public ActionResult Block()
{
// Your code
return PartialView("_Block.cshtml");
}
Related
I've been reading too many tutorials already and none of it explain what this means in an action result
return View(model);
Why can't we simple return view?
Why do we put a model parameter in our action result's return view()?
Also, anyone can give an example for a situation where I have to use return view(model)?
Because your view uses the model to build its content.
If you had a model like this:
public class Order
{
public decimal Total { get; set; }
}
And your controller:
public ActionResult GetOrderInformation(int orderID)
{
var order = LoadOrder(orderID);
return View(order);
}
With this view:
#model Order
<html>
<head> </head>
<body>
Your order costs #Model.Total
</body>
</html>
You can see how the view is completely independent from the controller, or how the information is retrieved - which is the whole idea behind MVC. The view only knows about the model, and how to display the model - nothing else.
The controller knows who to ask for the data, but not how to display it
You don't need to.
If the view you are rendering is static with no info needed from the controller then you can just end your Action with a return View();
public ActionResult SomeAction()
{
...
return View();
}
Then in your .cshtml file don't declare any #model directive and it'll be fine.
You can return simply view, but when you pass the model into view your can use it as you viewbag, and by that bind view elements with the model data.
You can simply use
return View();
but if you need to bind data then you have to pass like
return View(model);
for an example
Model Class
public class BookViewModel
{
public Guid Id { get; set; }
public string Name { get; set; }
}
Controller Method
public ActionResult Index()
{
return View();
}
public ActionResult Create()
{
return View(new BookViewModel());
}
View
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.Id)
<div class="editor-label">
#Html.LabelFor(m => m.Name)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
</div>
}
You don't need to pass objects to an action result, although if you don't you can't access the model.
i.e. It is common to do this on static pages such as About screens:
public ActionResult About() {return View();}
Also, it is possible to pass other objects instead of the full model.
See post: Must ASP.NET MVC Controller Methods Return ActionResult?
In Asp.net MVC, View(chtml) is for redering UI;
if your View is simple or static, you can construct your html content in the View without external data.
If you need data (from Db, web service, etc), your View must be able to query the data source.
There are several ways to pass data to view; via the View(Model) statement, via viewbag, etc.
we can also pass service layer object so view can query the datasource by itself.
Why do we need to pass Model to View again? Once in View (cshtml) you cannot access Controller -> you can pass ready to read data or service layer object inside your Model
You can just return a view:
View()
In that view, you won't have a #model you can take data of. You can still pass ViewBag or ViewData to send some dynamic data to the view.
Is it possible to have a View without a model?
YES
Some cases:
Semi static page: You don't need a model because almost everything that will be displayed in the page is static.
Container page: It can contain a lot of partials views, javascript calls or whatever you can imagine to retrieve data dinamically.
Many other cases in which the existence of a Model doesn't correspond to a business logic (or a good practice logic)
Just remember that patrons are there to guide us, not to force us to do things just one way. Check what's best for your application, change the bits that you don't like. Try to take the best of the framework, but remember it is there to help you.
I am trying to pass an value from my view to my controller:
public ActionResult Create(int id)
{
ViewBag.ConferenceRegesterId = id;
return View();
}
As you can see in create action i save my id in viewbag .i need this id in post back so i have this code for postback :
[HttpPost]
public ActionResult Creat(MvcConference.Models.Details1 ObjDetails)
{
dbcontext.Details1.Add(ObjDetails);
dbcontext.SaveChanges();
List<MvcConference.Models.Details1> lstuser = dbcontext.Details1.ToList();
return View("Index");
}
I use this code to assign my viewbag value to my model item in my create view
#Html.HiddenFor(model => model.ConferenceRegesterId=ViewBag.ConferenceRegesterId)
but finally after executing i got this error :
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1963: An expression tree may not contain a dynamic operation
I will be apprciate for any help
Best regards
You can't just assign the value for a model's property in a view (through viewbag) like the way you're currently doing, because you're not creating an instance of the class. Please note that only value bound to the input elements are posted back to the controller.
Slightly change the way your program currently behaves. Your create action in the controller will crate an instance for your viewmodel and initialize the required members (ConferenceRegesterId). This model will be strongly bound to the create view.
public ActionResult Create(int id)
{
MvcConference.Models.Details1 viewmodel = new MvcConference.Models.Details1();
viewmodel.ConferenceRegesterId = id;
return View(viewmodel);
}
Your create view
#model MvcConference.Models.Details1
#using (Html.BeginForm())
{
......
#Html.HiddenFor(model => model.ConferenceRegesterId)
}
Now your ObjDetails in POST action can access the value of ConferenceRegesterId you passed through the hiddenfield input element.
You don't need any model. That's simple problem. When you use a ViewBag you must convert that object to static object on your Razor View.
Like that;
#{
string varName = ViewBag.varName;
}
And you will not see again that;
Compiler Error Message: CS1963: An expression tree may not contain a dynamic operation
I have to pass a model object to my create view , so that on submit click this model object gets updated.
But at the same time iam using a list of data in its main Layout for rendering a dynamic menu.
Both use the same model class. But for one i give as
#model IEnumerable<DynaPortalMVC.Models.Page>
and in the create view i give as
#model DynaPortalMVC.Models.Page
In Controller:-
public ActionResult Create()
{
return View();
}
But this gives me an error in _Layout.cshtml, hence the above actionresult is not even executed.
Exception Details: System.ArgumentNullException: Value cannot be null.Parameter name: source
So i think i should pass the Ienumerable object to create view and then convert it there to simple model object, so that it can be updated. Please advice on this.
It's questionable whether you should have #model directive in your Layout. In my opinion you should render your dynamic menu by using a partial view and an action in your controller invoked from Layout by calling HtmlHelper.Action method, something like this:
Partial view for the menu (file named _Menu.cshtml):
#model IEnumerable<DynaPortalMVC.Models.Page>
<ul>
#foreach (var page in Model)
{
<li>#page.Name</li>
}
</ul>
Action named _Menu in your Home controller (or any other):
public ActionResult _Menu()
{
IEnumerable<DynaPortalMVC.Models.Page> model = new List<DynaPortalMVC.Models.Page>
{
new DynaPortalMVC.Models.Page { Name = "Page1" },
new DynaPortalMVC.Models.Page { Name = "Page2" },
new DynaPortalMVC.Models.Page { Name = "Page3" },
new DynaPortalMVC.Models.Page { Name = "Page4" },
};
return PartialView("_Menu", model);
}
This line of code in your Layout to render a menu:
#Html.Action("_Menu", "Home")
I am new to Asp.net MVC and have no idea as to how can i perform the search. Here's my requirement, please tell me how will you handle this :-
I need to have textbox where user can enter a search query or string. The user then clicks on a button or presses enter to submit it. The string needs to matched with a table's property name.
NOTE:- Querying the data and fetching the result isn't the main point here. All I need to know is how will you take the user input and pass it to a controller action or whatever for further processing. Just tell me how will you read the user input and where will you send it to search.
Asp.Net MVC uses standard HTTP verbs. For the html part, it's a normal html form that points to an url. Server side, that url will be routed to a controller/action which will handle the input and do what is needed.
Let's have a sample. You want to make a search form. First of all, it's a best practice to have search forms use the HTTP GET method instead of POST, so the search results can be bookmarked, linked, indexed, etc. I won't be using Html.BeginForm helper method to make things more clear.
<form method="get" action="#Url.Action("MyAction", "MyController")">
<label for="search">Search</label>
<input type="text" name="search" id="search" />
<button type="submit">Perform search</button>
</form>
That's all the html you need. Now you'll have a controller called "MyController" and the method will be something like this:
[HttpGet]
public ActionResult MyAction(string search)
{
//do whatever you need with the parameter,
//like using it as parameter in Linq to Entities or Linq to Sql, etc.
//Suppose your search result will be put in variable "result".
ViewData.Model = result;
return View();
}
Now the view called "MyAction" will be rendered, and the Model of that view will be your "result". Then you'll display it as you wish.
As always in an ASP.NET MVC application you start by defining a view model which will express the structure and requirements of your view. So far you have talked about a form containing a search input:
public class SearchViewModel
{
[DisplayName("search query *")]
[Required]
public string Query { get; set; }
}
then you write a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new SearchViewModel());
}
[HttpPost]
public ActionResult Index(SearchViewModel model)
{
if (!ModelState.IsValid)
{
// There was a validation error => redisplay the view so
// that the user can fix it
return View(model);
}
// At this stage we know that the model is valid. The model.Query
// property will contain whatever value the user entered in the input
// So here you could search your datastore and return the results
// You haven't explained under what form you need the results so
// depending on that you could add other property to the view model
// which will store those results and populate it here
return View(model);
}
}
and finally a view:
#model SearchViewModel
#using (Html.BeginForm())
{
#Html.LabelFor(x => x.Query)
#Html.EditorFor(x => x.Query)
#Html.ValidationMessageFor(x => x.Query)
<button type="submit">Search</button>
}
This is the best way to do it.
Create a ViewModel
public class SearchViewModel
{
public string Query { get; set; }
}
Create a Controller
public class SearchController : Controller
{
[HttpPost]
public ActionResult Search(SearchViewModel model)
{
// perform search based on model.Query
// return a View with your Data.
}
}
Create the View
// in your view
#using (Html.BeginForm("Search", "SearchController"))
{
#Html.TextBox("Query")
<input type="submit" value="search" />
}
hope this helps
So I am new to ASP.NET MVC and I would like to create a view with a text box for each item in a collection. How do I do this, and how do I capture the information when it POSTs back? I have used forms and form elements to build static forms for a model, but never dynamically generated form elements based on a variable size collection.
I want to do something like this in mvc 3:
#foreach (Guest guest in Model.Guests)
{
<div>
First Name:<br />
#Html.TextBoxFor(???) #* I can't do x => x.FirstName here because
the model is of custom type Invite, and the
lambda wants to expose properties for that
type, and not the Guest in the foreach loop. *#
</div>
}
How do I do a text box for each guest? And how do I capture them in the action method that it posts back to?
Thanks for any help.
Definitely a job for an editor template. So in your view you put this single line:
#Html.EditorFor(x => x.Guests)
and inside the corresponding editor template (~/Views/Shared/EditorTemplates/Guest.cshtml)
#model AppName.Models.Guest
<div>
First Name:<br />
#Html.TextBoxFor(x => x.FirstName)
</div>
And that's about all.
Now the following actions will work out of the box:
public ActionResult Index(int id)
{
SomeViewModel model = ...
return View(model);
}
[HttpPost]
public ActionResult Index(SomeViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// TODO: do something with the model your got from the view
return RedirectToAction("Success");
}
Note that the name of the editor template is important. If the property in your view model is:
public IEnumerable<Guest> Guests { get; set; }
the editor template should be called Guest.cshtml. It will automatically be invoked for each element of the Guests collection and it will take care of properly generating ids and names of your inputs so that when you POST back everything works automatically.
Conclusion: everytime you write a loop (for or foreach) inside an ASP.NET MVC view you should know that you are doing it wrong and that there is a better way.
You can do this:
#for (int i = 0; i < Model.Guests.Count; i++) {
#Html.TextBoxFor(m => m.Guests.ToList()[i].FirstName)
}
There are more examples and details on this post by Haacked.
UPDATE: The controller post action should look like this:
[HttpPost]
public ActionResult Index(Room room)
{
return View();
}
In this example I'm considering that you have a Room class like this:
public class Room
{
public List<Guest> Guests { get; set; }
}
That's all, on the post action, you should have the Guests list correctly populated.