ViewViewdata.Model; what model does? - asp.net-mvc

ViewData.Model
i know that Viewdata contains the data that has been returned by view via
return view(//data);
but what does this .Model represents ?
Controller:
using Testing_linq.Models;
namespace Testing_linq.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
var DataContext = new RegistrationDataContext();
var Registration = DataContext.SelectRegistration_sp();
return View(Registration);
}
View:
<table>
#foreach(SelectRegistration_spResult reg in (IEnumerable<Object>)ViewData.Model)
{
<tr>
<td>#reg.userEmail </td>
</tr>
}
</table>
I'm using LInq to Sql classes in model.

The Model represents whatever dynamic information is required to render the page, and is something you provide to your view. For example, if you were going to create a View that shows a person's First name and Last name, you might come up with the following model:
public sealed class PersonViewModel
{
public string FirstName {get; set; }
public string LastName {get; set; }
}
It's preferable to use strongly-typed views, so the first line in your .cshtml file would be:
#model MyNameSpace.PersonViewModel
And when your controller returns the view, you would pass what needs to be rendered in to it:
public ActionResult Index()
{
return View(new PersonViewModel() { FirstName = "Moo", LastName = "Juice" });
}
ViewData.Model refers to the instance of the PersonViewModel passed in, and is accessed in your view via Model shortcut:
<body>
<p>
Hello #Model.FirstName !!
</p>
</body>

Related

How to pass 3 models data to asp.net MVC view [duplicate]

I am trying to generate such HTML
<form action="/some/process" method="post">
<input type="hidden" name="foo.a" value="aaa"/>
<input type="hidden" name="bar.b" value="bbb"/>
<input type="submit" />
</form>
so it can be processed by this Action:
public ActionResult Process(Foo foo, Bar bar)
{
...
}
Given the Action code
public ActionResult Edit()
{
ViewData["foo"] = new Foo { A = "aaa" };
ViewData["bar"] = new Bar { B = "bbb" };
return View();
}
what should I write in Edit.aspx view? I don't want to write names 'foo.a' and 'bar.b' manually.
String-indexed ViewData is bad. What you probably want to do is make a little wrapper class for your multi-variable view data and pass that to a strongly typed view. IE:
public class FooBarViewData
{
public Foo Foo {get; set;}
public Bar Bar {get; set;}
}
public ActionResult Edit()
{
FooBarViewData fbvd = new FooBarViewData();
fbvd.Foo = new Foo(){ A = "aaa"};
fbvd.Bar = new Bar(){ B = "bbb"};
return View(fbvd);
}
Then your view is just strongly typed to FooBarViewData and you can call members of that object using the Model property.
You have a couple of choices. First, you can reference them from ViewData and use an HtmlHelper extension. Or you could create a view-specific model and use a strongly-typed viewpage for Edit.aspx.
public class EditModel
{
public Foo foo { get; set; }
public Bar bar { get; set; }
}
public ActionResult Edit()
{
var model = new EditModel();
model.foo = new Foo { A = "aaa" };
model.bar = new Bar { B = "bbb" };
return View( model );
}
(Edit.aspx is of type ViewPage<EditModel>)
Either way, the HtmlHelper extension will pick up any initial values.
<form action="/some/process" method="post">
<%= Html.Hidden( "foo.A" ) %>
<%= Html.Hidden( "bar.B" ) %>
</form>
The solution above may be outdated. This solution seems to work for ASP.Net MVC5+.
You're going to have to use the ViewModel method. This is an excellent tutorial that you can check out.
http://tutlane.com/tutorial/aspnet-mvc/how-to-use-viewmodel-in-asp-net-mvc-with-example
You are going to have to join multiple models into one ViewModel and grab all the properties from each models you want to use into the ViewModel.
BUT, it is HIGHLY advised that you create a new Controller and a new View to accomodate the newly created ViewModel. Read the tutorial.
public class FooBarViewModel
{
public string A {get; set;} //Property for Foo
public string B {get; set;} //Property for Bar
}
public ActionResult Edit()
{
FooBarViewModel fooBarVM = new FooBarViewModel();
fooBarVM.A = "aaa";
fooBarVM.B = "bbb";
return View(fooBarVM);
}
But in this case, you should be able to pass the ViewModel into a different view. Just make sure you declare this similar directive correctly in the foobar.cshtml page.
#model FooBar.Models.FooBarViewModel
I was struggling for a while trying to get two models to work, and most of the answers I came across was meant for earlier versions of MVC.
I found the following tutorial works best for MVC 5 as suggested by David Lee:
http://tutlane.com/tutorial/aspnet-mvc/how-to-use-viewmodel-in-asp-net-mvc-with-example
I created a join and selected only the columns I needed from both Models.
I had it working with partial views
In view.cshtml
#model IEnumerable<Test.Models.TestViewModel>
...
#foreach (var item in Model)
{
<tr>
<td style="text-align:center;vertical-align:middle">
#Html.DisplayFor(modelItem => item.TestName)
...

BeginForm in ChildAction uses wrong id

There is something simple I don't understand with ChildActions.
I've created a simple View for a model, that loads a child action with a form.
The child action has another model than its parent, with a different id property.
Html.HiddenFor(m => m.Id) still outputs the parents id, although #Model.id outputs the correct value!
Can't I reliably use the Helper methods in ChildActions, or is this a known bug?
HomeController
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new Models.HomeModel { id = 1, message = "bugmodel" };
return View(model);
}
[HttpGet]
[ChildActionOnly]
public ActionResult Child(int id)
{
var model = new Models.HomeChildModel { id = 100, parentId = id, childMessage = "My Child message" };
return PartialView(model);
}
[HttpPost]
[ActionName("Child")]
[ValidateAntiForgeryToken()]
public ActionResult ChildPost(Models.HomeChildModel model)
{
return RedirectToAction("Index");
}
}
Models
public class HomeModel
{
public int id { get; set; }
public string message { get; set; }
}
public class HomeChildModel
{
public int id { get; set; }
public int parentId { get; set; }
public string childMessage { get; set; }
}
Home view
#model ChildActionBug.Models.HomeModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.DisplayFor(m=>m.id)
#Html.DisplayFor(m=>m.message)
#Html.Action("Child", new { id = Model.id })
**Child view**
#model ChildActionBug.Models.HomeChildModel
<h3>Child here</h3>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m=>m.id)
#Html.HiddenFor(m=>m.parentId)
#Html.EditorFor(m=>m.childMessage)
<div>Child Model ID: #Model.id</div>
<button type="submit">Save</button>
}
Based on the answer given in the SO question I posted in the comment, you're better off explicitly creating the hidden fields
ASP.Net MVC Html.HiddenFor with wrong value
That's normal and it is how HTML helpers work. They first use the
value of the POST request and after that the value in the model. This
means that even if you modify the value of the model in your
controller action if there is the same variable in the POST request
your modification will be ignored and the POSTed value will be used.
So instead, hand craft the hidden fields:
<input type="hidden" name="Id" value="#Model.Id" />
<input type="hidden" name="ParentId" value="#Model.ParentId" />
<input type="hidden" name="ChildMessage" value="#Model.ChildMessage" />

How do I get a strongly typed DropDownList to bind to a control Action

I've just started a new MVC project and I'm having trouble getting the post result from a form.
This is my Model Class :
public class User
{
public int id { get; set; }
public string name { get; set; }
}
public class TestModel
{
public List<User> users { get; set; }
public User user { get; set; }
public SelectList listSelection { get; set; }
public TestModel()
{
users = new List<User>()
{
new User() {id = 0, name = "Steven"},
new User() {id = 1, name = "Ian"},
new User() {id = 2, name = "Rich"}
};
listSelection = new SelectList(users, "name", "name");
}
}
This is my view class
#model MvcTestApplicaiton.Models.TestModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
#if (#Model.user != null)
{
<p>#Model.user.name</p>
}
And this is my controller :
public class TestModelController : Controller
{
public TestModel model;
//
// GET: /TestModel/
public ActionResult Index()
{
if(model ==null)
model = new TestModel();
return View(model);
}
[HttpPost]
public ActionResult Test(TestModel test)
{
model.user = test.user;
return RedirectToAction("index", "TestModel");
}
}
The drop down list appears just fine but I can't see to get the ActionResult Test function to run. I thought it would just bind itself with reflection but whatever is wrong, I can't see it.
You have two main errors in your code.
As Brett said you're posting to the Index method, but you don't have Index method that supports POST verb. The easiest way to fix is to change Html.BeginForm() with Html.BeginForm("Test", "TestModel")
You're using Html.DropDownListFor in a wrong way. You could pass only a value types there, because don't forget that the View will generate an HTML page. So instead of User in your Model you should have an UserID and in your View you should have #Html.DropDownListFor(x => x.UserID, #Model.listSelection). And finally in your Action you should query your data source to get the details for the user with this ID.
Hope this helps.
Looks like you're posting back to index. Either use a GET Test() action method, or specify the ACTION parameter in BeginForm().
For example,
#using (Html.BeginForm("Test", "TestModel"))
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
Or use a view named Test (rename index.cshtml to test.cshtml):
public ActionResult Test()
{
if(model ==null)
model = new TestModel();
return View(model);
}

How can i do search inside same page in MVC Razor

How can i do search inside same page in MVC Razor? For example; my page do not any result when open if i search return.i must use IEnumerable<model> for getting result but if i use IEnumerable<model> for empty page, i am getting error.
Search page
#model IEnumerable<SearchResult>
<span>Search results:</span>
<p>
#foreach(var item in Model)
{
#item.Title<br/>
}
</p>
You need to return empty model for such case. for example in controller code:
public ActionResult Test()
{
// some actions
return View(new List<SearchResult>());
}
in that case it will send empty model, and won't fail.
You can create a model that contain the search properties and the result list.
Model
Public class MySearchModel{
public string searchInput { get; set; }
public List<mySearchResultModel> resultList { get; set; }}
Controller
public ActionResult Index()
{
var model = new MySearchModel();
return View(model);
}
[HttpPost]
public ActionResult Index(MySearchModel model)
{
model.searchInput //filter
model.mySearchResultModel = //query where filter
return View(model);
}
View
#model MySearchModel
<div>
#Html.LabelFor(x => x.searchInput)
#Html.TextBoxFor(x => x.searchInput)
</div>
<span>Search results:</span>
#foreach (var item in Model.mySearchResultModel){
#item.Title<br />
}
Another way to accomplish the same is to add your search inputs and map them to the controller action that you are posting using the input name:
Controller
public ActionResult Index()
{
var model = new mySearchResultModel();
return View(model);
}
[HttpPost]
public ActionResult Index(mySearchResultModel model, string searchInput)
{
model.mySearchResultModel = //query where filter (searchInput)
return View(model);
}
View
#model IEnumerable<mySearchResultModel>
<input type="text" name="searchInput"/>
Search results:
#foreach(var item in Model) { #item.Title<br/> }

MVC 3 using #model twice

I would like to using two times #model to get data from another part of my website is it possible? Because now I have got error but if I have only this first #model everything working correct.
Look -> MVC 3 - Exception Details: System.InvalidOperationException
Error 2 'SportsStore.Entities.Kategorie' does not contain a definition for 'Opis' and no extension method 'Opis' accepting a first argument of type 'SportsStore.Entities.Kategorie' could be found (are you missing a using directive or an assembly reference?) c:\Users\Rafal\Desktop\MVC ksiązka\moj projekt\sklep\SportsStore.WebUI\Views\Product\List.cshtml 16 4 SportsStore.WebUI
#model IEnumerable<SportsStore.Entities.Towar>
#model IEnumerable<SportsStore.Entities.Kategorie>
#{
ViewBag.Title = "List";
}
<h2>List</h2>
#foreach (var p in Model)
{
<div class="item">
<h3>#p.Nazwa</h3>
#p.Opis
<h4>#p.Cena.ToString("c")</h4>
</div>
}
You only can have one Model per View. But you can use another object to declarate the model:
public class SomeViewModel
{
public IEnumerable<Towar> Towars;
public IEnumerable<Category> Categories;
public SomeViewModel(IEnumerable<Towar> towars, IEnumerable<Category> categories) {
Towars = towars;
Categories = categories;
}
}
And then use it in your view like this:
#model SportsStore.Entities.SomeViewModel
#foreach (var item in Model.Towars)
{
<div class="item">
<h3>#p.Nazwa</h3>
#p.Opis
<h4>#p.Cena.ToString("c")</h4>
</div>
}
#foreach (var item in Model.Categories) {
#item.Name #* or what you need down here *#
}
I would also recommend you to use english names in MVC. It's more clear to read and understand ;).
I think this would be a case to create a ViewModel (to combine the two entities you have) and then base a View off that ViewModel.
It is best to create a view model to represent your data. Your view model must only contain what you need to display on your view. Anything that is not used you can remove, no point of it being there. Your view model can look like this:
using SportsStore.Entities;
public class YourViewModel
{
public IEnumerable<Towar> Towars { get; set; }
public IEnumerable<Kategorie> Categories { get; set; } // I assume this is categories
}
Lets say that you have to use this view model in a create view then your create action can look something like this:
public class YourController : Controller
{
private readonly ITowarRepository towarRepository;
private readonly ICategoryRepository categoryRepository;
public YourController(ITowarRepository towarRepository, ICategoryRepository categoryRepository)
{
this.towarRepository = towarRepository;
this.categoryRepository = categoryRepository;
}
public ActionResult Create()
{
YourViewModel viewModel = new YourViewModel
{
Towars = towarRepository.GetAll(),
Categories = categoryRepository.GetAll()
};
return View(viewModel);
}
}
And then in your view:
#model YourProject.DomainModel.ViewModels.YourViewModel
#foreach (var towar in Model.Towars)
{
// Do whatever
}
#foreach (var category in Model.Categories)
{
// Do whatever
}

Resources