How to send and retrieve in the controller - asp.net-mvc

I have the folowing code in my view, however, I can see that I don`t have the values in the controller. What is wrong?
In the view I have,
<%
using (Html.BeginForm())
{%>
<%=Html.TextBox("Addresses[0].Line1") %>
<%=Html.TextBox("Addresses[0].Line2")%>
<%=Html.TextBox("Addresses[1].Line1")%>
<%=Html.TextBox("Addresses[1].Line2")%>
<input type="submit" name="submitForm" value="Save products" />
<%
}
%>
My classes are as follows:
public class Customer
{
public string FirstName { get; set; }
public string Lastname { get; set; }
public List<Address> Addresses { get; set; }
public Customer()
{
Addresses = new List<Address>();
}
}
public class Address
{
public int Line1 { get; set; }
public int Line2 { get; set; }
}
My controller as follows:
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Customer customer)
{
return View();
}

The parameter for your ActionResult is named customer, so the default model binder will be looking for that name in the form by default. I believe if you modify your code to the following it should pick it up:
<%=Html.TextBox("customer.Addresses[0].Line1") %>
<%=Html.TextBox("customer.Addresses[0].Line2")%>
<%=Html.TextBox("customer.Addresses[1].Line1")%>
<%=Html.TextBox("customer.Addresses[1].Line2")%>

Check to ensure your View is bound to the Customer model.
Also, when viewing the web page containing the form, view the source generated by the View to see if the fields are being properly named.
Finally, if none of the above helps, change the parameter in your Index action like so:
public ActionResult Index(FormCollection form)
then you can use the debugger to inspect the FormCollection object that is passed in to see exactly what the View is sending you.

Related

MVC sending a form to a page for testing

I am using MVC and have a view (test.cshtml) that contains a form. Is there a way to send it to another View page.cshtml for testing instead of same [http] controller ActionResult test()?
I am trying to validate that all the form field values are correct before updating db. Is there an easier way to do this?
In your view
#using (Html.BeginForm("Add", "Weight", FormMethod.Post))
//where "Add" is the Action name and Weight is the controller (WeightController) -> http://foo/Weight
{
......
}
With a model
public class WeightModel
{
[Required] public string Description { get; set; }
[Required] public int Weight { get; set; }
public string Notes { get; set; }
}
In your Controller
[HttpPost]
public ActionResult Add(WeightModel model)
{
if (!ModelState.IsValid) //framwork will validate based on attributes on model
{
return View("Index", model);
}
else
{
//save to db
return RedirectToAction("Added");
}
}

asp.net mvc rendering partial view on-demand

I'm a newbie to asp.net mvc and I'd like to know if what I do is correct.
I want to create a view for searching people. Here's what I have so far:
The business model class:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
public DateTime DOB { get; set; }
public List<Telephone> Telephones { get; set; }
}
The ViewModel class:
public class SearchPersonViewModel
{
public int Id { get; set; }
public string FullName { get; set; }
public string LicencePlate { get; set; }
public string CarMake { get; set; }
public string CarModel { get; set; }
}
The partial view :
#model IEnumerable<MvcApplication2.Models.SearchPersonViewModel>
#foreach (var item in Model)
{
#Html.DisplayFor(m => item.Id)
#Html.DisplayFor(m => item.FullName)
}
The view from which the partial view is called:
#Html.Action("Search", "Person");
*The controller method in the PersonController:
[ChildActionOnly]
public ActionResult Search()
{
List<SearchPersonViewModel> model = new List<SearchPersonViewModel>();
model.Add(new SearchPersonViewModel() { FullName = "test", Id = 3 });
return PartialView("_SearchPerson", model);
}
Now the problem is that the Search method is called whenever the main View is loaded. What I want is to add a search textbox on the mainview for filtering the collection rendered in the partial view. How could I do that ?
This way your partial will render on click only
<script>
(function($){
$('#btn').click(function(){
$('#searchresult').load('#Url.Content("~/Person/Search")');
}
</script>
Make an ajax request to /search and append the data to your page.
<div id = 'searchresult'>
#Html.Action("Search", "Person");
</div>
whenever your want to filter call something like $('#searchresult').load('/search?q=xxx');
You could use 2 ways:
microsoft ajax helpers
jquery
For both of them you need to remove [ChildActionOnly] and #Html.Action("Search", "Person");
Look at this example: Using Ajax.BeginForm with ASP.NET MVC 3 Razor

Submitting twitter bootstrapper tabs, with asp.net mvc 3 partial view

I am having a twitter bootstraper tab, with 3 simples tabs (Caracteristiques, Certificat and Contrats)
the tabs are ajax load with asp.net mvc partialviews, they are tied with modelViews:
the partials views strongly tied to the type ViewModel:
// Load Certificat
public ActionResult Certificat()
{
var modelStaffs = _twitterTabsModel.GetStaffs();
return PartialView("_Certificat", modelStaffs);
}
// load Contrats
public ActionResult Contrats()
{
var modelJoueur = _twitterTabsModel.GetFirstJoueur();
return PartialView("_Contrats", modelJoueur );
}
the models:
public class TwitterTabModel
{
public ModelJoueur JoueurVM { get; set; }
public IEnumerable<ModelStaff> StaffVM { get; set; }
}
public class ModelStaff
{
public string NomStaff { get; set; }
public string FonctionStaff { get; set; }
}
public class ModelJoueur
{
public string NomJoueur { get; set; }
public string PrenomJoueur { get; set; }
}
the Caracteristiques Tab views:
#model Controls.Models.ViewModel.TwitterTabModel
<h2>Caracteristiques</h2>
#using (Html.BeginForm())
{
.... the tabs code ...
<p>
<input type="submit" value="Save" />
</p>
}
The tabs load fines, what I want to do is to include a submit button on the first razor view tab, it submit all the other models if loaded, however, when I get the post call, all the others models, JoueurVM and StaffVM are empty even though they are loaded. Why is it according to you ?
edit: This is the controller post code, nothing special, just trying to get the twitterTabModel:
[HttpPost]
public ActionResult Tabs(TwitterTabModel model)
{
return View();
}
Thanks
I figure a workaround, I pass the input values back as formcollection, instead of the overall model, well it it' s not clean, but well, it works as i can get all the values posted

DefaultModelBinder not binding nested model

Looks like others have had this problem but I can't seem to find a solution.
I have 2 Models: Person & BillingInfo:
public class Person
{
public string Name { get; set;}
public BillingInfo BillingInfo { get; set; }
}
public class BillingInfo
{
public string BillingName { get; set; }
}
And I'm trying to bind this straight into my Action using the DefaultModelBinder.
public ActionResult DoStuff(Person model)
{
// do stuff
}
However, while the Person.Name property is set, the BillingInfo is always null.
My post looks like this:
"Name=statichippo&BillingInfo.BillingName=statichippo"
Why is BillingInfo always null?
I had this problem, and the answer was staring me in the face for a few hours. I'm including it here because I was searching for nested models not binding and came to this answer.
Make sure that your nested model's properties, like any of your models that you want the binding to work for, have the correct accessors.
// Will not bind!
public string Address1;
public string Address2;
public string Address3;
public string Address4;
public string Address5;
// Will bind
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string Address4 { get; set; }
public string Address5 { get; set; }
Status no repro. Your problem is elsewhere and unable to determine where from what you've given as information. The default model binder works perfectly fine with nested classes. I've used it an infinity of times and it has always worked.
Model:
public class Person
{
public string Name { get; set; }
public BillingInfo BillingInfo { get; set; }
}
public class BillingInfo
{
public string BillingName { get; set; }
}
Controller:
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new Person
{
Name = "statichippo",
BillingInfo = new BillingInfo
{
BillingName = "statichippo"
}
};
return View(model);
}
[HttpPost]
public ActionResult Index(Person model)
{
return View(model);
}
}
View:
<% using (Html.BeginForm()) { %>
Name: <%: Html.EditorFor(x => x.Name) %>
<br/>
BillingName: <%: Html.EditorFor(x => x.BillingInfo.BillingName) %>
<input type="submit" value="OK" />
<% } %>
Posted values: Name=statichippo&BillingInfo.BillingName=statichippo is perfectly bound in the POST action. Same works with GET as well.
One possible case when this might not work is the following:
public ActionResult Index(Person billingInfo)
{
return View();
}
Notice how the action parameter is called billingInfo, same name as the BillingInfo property. Make sure this is not your case.
I had the same issue, the previous developer on the project had the property registered with a private setter as he wasn't using this viewmodel in a postback. Something like this:
public MyViewModel NestedModel { get; private set; }
changed to this:
public MyViewModel NestedModel { get; set; }
This is what worked for me.
I changed this:
[HttpPost]
public ActionResult Index(Person model)
{
return View(model);
}
To:
[HttpPost]
public ActionResult Index(FormCollection fc)
{
Person model = new Person();
model.BillingInfo.BillingName = fc["BillingInfo.BillingName"]
/// Add more lines to complete all properties of model as necessary.
return View(model);
}
public class MyNestedClass
{
public string Email { get; set; }
}
public class LoginModel
{
//If you name the property as 'xmodel'(other than 'model' then it is working ok.
public MyNestedClass xmodel {get; set;}
//If you name the property as 'model', then is not working
public MyNestedClass model {get; set;}
public string Test { get; set; }
}
I have had the similiar problem. I spent many hours and find the problem accidentally that I should not use 'model' for the property name
#Html.TextBoxFor(m => m.xmodel.Email) //This is OK
#Html.TextBoxFor(m => m.model.Email) //This is not OK

Lookup lists with NHibernate and ASP.Net MVC

I can't seem to get the value of a select list to populate the value of the parent object.
I'm using a wrapper object to bind to so that I have access to the values needed for the SelectList as well as the object which needs the value.
I'm willing to bet I'm missing something basic but I can't find it.
I have these models:
public class Status
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual bool IsClosed { get; set; }
public override string ToString()
{
return Name;
}
}
public class Issue
{
public virtual int Id { get; protected set; }
public virtual string Title { get; set; }
public virtual string Description { get; set; }
public virtual Status Status { get; set; }
public virtual DateTime CreatedOn { get; set; }
public virtual DateTime UpdatedOn { get; set; }
}
And a FormViewModel (from NerdDinner examples) to contain the list of Statuses
public class IssueFormViewModel
{
public Issue Issue { get; set; }
public SelectList Statuses { get; set; }
public IssueFormViewModel(Issue issue, IList<Status> statuses)
{
Issue = issue;
Statuses = new SelectList(statuses, "Id", "Name", statuses[1].Id );
}
public IssueFormViewModel() { }
}
My Create Actions on the Controller look like...
public ActionResult Create()
{
IList<Status> statuses;
Issue issue = new Issue();
// NHibernate stuff getting a List<Status>
return View(new IssueFormViewModel(issue,statuses));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(IssueFormViewModel issueFormView)
{ // At this point issueFormView.Issue.Status == null
// ...
}
My Issue object is bound partially except the status using these names in the View:
<p>
<label for="Issue.Title">Title:</label>
<%= Html.TextBox("Issue.Title", Model.Issue.Title)%>
<%= Html.ValidationMessage("Title", "*") %>
</p>
<p>
<label for="Statuses">Status:</label>
<!-- also tried "Issue.Status" -->
<%= Html.DropDownList("Statuses", Model.Statuses)%>
<%= Html.ValidationMessage("Status", "*")%>
</p>
I tried the dropdown list on my computer and it works, you should make sure NHibernate is bringing back more than 1 item as your code is trying to set the selected item to be the second item.
Statuses = new SelectList(statuses, "Id", "Name", statuses[1].Id);
Remember that Lists a re zero based indexed.
As expected - it WAS something simple.
I changed the view to look like:
<label for="Status.Id">Status:</label>
<%= Html.DropDownList("Status.Id", Model.Statuses)%>
<%= Html.ValidationMessage("Status.Id", "*")%>
and the controller signature to take an "issue" (can't bind to a selectlist!)
[AcceptVerbs(HttpVerbs.Post)]
//public ActionResult Create(IssueFormViewModel issueFormView)
public ActionResult Create(Issue issueToAdd)
{
And in my Post-Create action I have an Issue with a Status. Albeit the status is invalid (it only contains the Id). So before commiting the Issue to the db, I set the issueToAdd like this:
issueToAdd.Status = (from p in GetAllStatuses()
where p.Id == issueToAdd.Status.Id
select p).First();
Edit: And it turns out I didn't even need to fetch a "proper" Status object. It's bound to Id and that's good enough.

Resources