I have a model that has a property which is a collection. I can successfully bind from the edit actions, for example:
[HttpGet]
public ActionResult Edit(string id)
{
// code here
return this.View(complexModel);
}
[HttpPost]
public ActionResult Edit(ComplexModel complexModel)
{
// code here
return RedirectToAction("AnotherAction")
}
In the post method I can successfully receive all the object properties, including the collection one. However I have another view that can invoke the Edit action. When this happens I can see that the html rendered is the same (i.e. the nested property info is there). When I save the changes in the post Edit I receive all the correct properties with one exception - the collection propery has zero items.
Where do I have to search for the problem?
Update:
I am properly iterating through the collection and displaying all items with EditorFor; however when coming from a differnt view (the different view is in another controller and the Edit link is placed in a Display Template - if that makes any difference) with the same exact model I can see that the html is the same since all the properties of the collection are there.
Ok, false alarm. I figured it out - I am invoking the action method using #Html.ActionLink; I was passing the whole model instead of just the id. I do not know for what silly reason things got messed up, but they are ok now.
What does your Edit view look like? You need to iterate over all the items in the collection as form elements.
Related
I am new to MVC and ASP.NET. My requirement is, I have to display two records in my View for the firsttime and my ViewContains one 'SWAP' button. When I press this button, post action of the controller should execute and it has to take the original viewmodel and needs to swap the two records and should render the same view. This process should carryon whenever I press Swap button.
For the first time when I am clicking SWAP, it is working fine. But when I am clicking for next time, my post controller action is taking original records and displaying the same.
My Controller Code as shown Below.
public ActionResult Dedupe()
{
var selectedClients = TempData["SelectedClients"] as DedupeClientsViewModel;
return this.View(selectedClients);
}
[HttpPost]
public ActionResult Dedupe(DedupeClientsViewModel dedupeClients)
{
if (ModelState.IsValid)
{
//my functionality
}
return this.View(dedupeClients);
}
Is there anything that I need to do with "ModelState" to get the new data from the View.
Because you are returning the same model from a post, ASP.Net MVC is assuming that you have errors that you want to present back to the user (so it retains original values). You can fix this by either clearing the model state for the entire model, or clearing the model state for one or more fields. See below. This will be done, of course, in your controller.
ModelState.Clear(); //clear entire model state
ModelState.Remove("MyObject.MyProperty"); //clear only one property
Rick Strahl has a good explanation of this issue on his blog: ASPNET-MVC-Postbacks-and-HtmlHelper-Controls-ignoring-Model-Changes
In the process of updating a C# MVC 2.0 application!
I have a view “Signup” and another view “ForgotPassword”.
Each view have a with a submit button.
Each form is submitted to the same Controller but to two different ActionResult:
[HttpPost]
public ActionResult Signup(SignupModel signupModel)
{…}
[HttpPost]
public ActionResult ForgotPwd(ForgotPasswordModel forgotPasswordModel)
{…}
Upon completion my goal is to redirect the user to a “thankyou” page but based on where the user is coming from (either Signup or ForgotPassword) I wish to display a particular message (or a different UI).
Inside the same Controller, I created a “Thankyou” ActionResult:
public ViewResult Thankyou()
{
return View();
}
I was thinking of adding a parameter to my Thankyou() method which would allow me to know where the user is coming from (Signup or ForgotPwd). From there, make the “thankyou” page display the appropriate UI/message.
I’m looking for a clean and simple solution.
Should I create two View User Controls and show the appropriate one based on the parameter being passed?
In addition, instead of having an “ActionResult” for my Thankyou() method couldn’t I use a “PartialViewResult” ?
EDIT:
I was actually considering something along those lines…
Where ThankyouType is an Enum.
[HttpPost]
public ActionResult Signup(SignupModel signupModel)
{
//Validation code...
return View("Thankyou", ThankyouType.SignupDone);
}
[HttpPost]
public ActionResult ForgotPassword(ForgotPasswordModel forgotPasswordModel)
{
//Validation code...
return View("Thankyou", ThankyouType.ForgotPasswordDone);
}
And then have my “Thankyou” ViewResult like this:
public ViewResult Thankyou(ThankyouType type)
{
return View(type);
}
Doesn’t seem like I can create a strongly typed view based on Enum (unless I’m wrong).
Perhaps I’ll read more on PartialViewResults and/or find examples…but then again, I could be completely wrong.
I would personally give the ThankYou view a model that has the message you want to display, and have your two controller actions render the ThankYou view directly on success rather than calling a ThankYou action.
However, if you're sure you want a redirect, you may consider using the TempData collection to store a message or a key of some kind. The ThankYou controller can then retrieve this value and pass it to the View. This situation is what TempData was made for.
Edit
There's no reason you shouldn't be able to use an enum value as your model type, but if that gives you trouble you should at least be able to create a model type that has an enum property on it.
The strategy of sending the ThankYouType as part of the redirect request would work just fine, if that's what you prefer. The only potential downside is that it would look like this in the URL:
http://domain.com/controller/ThankYou?type=ForgotPasswordDone
I have no real arguments against it. There are lots of options. Use the one that feels best to you.
I have created a partial view in my asp.net mvc solution that will show a list of items from a database. However I get an error saying: Object reference not set to an instance of an object.
I'm not sure why this is happening because as far as I'm concerned everything is fine. The list of items are venues which is controlled via VenuesController BUT the partial view is inside the /shared/ folder and NOT the /venues/ folder for the views so is asp.net complaining because it's not linking the two together?
This is the code I have in my VenuesController:
//
// GET: /Venues/
public ActionResult Index()
{
return View(_repository.ListAll());
}
public ActionResult VenuesList()
{
return PartialView("VenuesList",_repository.ListAll());
}
The Index() works fine and displays the data in /Views/Venues/Index.aspx but the VenuesList() throws the error :/
Thanks.
The error message that you mention:
Object reference not set to an instance of an object.
typically deals when a property of a collection is referenced and it is null. You might want to make sure that the list of items is either:
Not empty.
Instantiated properly.
Any code from the Controller-side of things might make this a bit easier to figure out.
Update:
I'm not completely sure what the Venue model looks like, however two things could be occurring here.
In the constructor for Venue (which should be passed the list from your repository),
the List property inside of Venue is never being instantiated prior to Adding the
items in.
or
The repository is not returning any values.
Additional code displaying the Venue class and it's constructor might be helpful.
Make sure that any properties in your model that you reference in your partial view are not null. I've had similar cases where the model passed into the partial view has some null fields that, when rendered, throw NullReferenceExceptions.
E.g. something like
<%: Model.Property %>
or, especially:
<%: Model.Property.ChildProperty %>
i.e. if "Property" is null, then trying to access "ChildProperty" WILL throw a NulLReference exception.
Update following initial comments
The model has an object in it called 'Account', of which there is an int propety (Account.AccountID)
ViewB has a form which collects some additional information - but also has a textbox which is populated with Model.Account.AccountID.
When I submit ViewB however, Model.Account becomes null.
Its probably easier to show a simplified version of what I have before I explain the issue:
[HttpGet]
public ActionResult ViewA()
{
return View(new BlahModel());
}
[HttpPost]
public ActionResult ViewA(BlahModel model)
{
if(there_was_a_problem)
return View("ViewA", model);
else
return View("ViewB", model);
}
// have tried both httppost, httpget and no attribute here
public ActionResult ViewB(BlahModel model)
{
return View(model);
}
I load up ViewA via a GET, fill in the strongly-typed form and submit - then the following View (either ViewA again or ViewB if the request had no problems) is fine ... it has full access to the whole model and can display the properties within it.
The problem is that if I then submit a form in ViewB (which posts to the ActionResult ViewB) - the model suddenly has null properties throughout, even though its using the same model - and prior to the post has picked up all the values sucessfully.
Any ideas?
Many thanks
Most likely - ViewB view does not render enough and model binder can't find values to bind.
Action argument is binded from form values. It does not matter if You pass model to view correctly. Rendering things out is what matters (or passing through query string/cookies).
Complementing Arnis L.'s answer, you can use a tool like Firebug to check that your model's parameters (or any parameters at all) are being sent along the request.
I have a usercontrol that is rendering a list of items. Each row contains a unique id in a hidden field, a text and a delete button. When clicking on the delete button I use jquery ajax to call the controller method DeleteCA (seen below). DeleteCA returns a new list of items that replaces the old list.
[HttpPost]
public PartialViewResult DeleteCA(CAsViewModel CAs, Guid CAIdToDelete)
{
int indexToRemove = CAs.CAList.IndexOf(CAs.CAList.Single(m => m.Id == CAIdToDelete));
CAs.CAList.RemoveAt(indexToRemove);
return PartialView("EditorTemplates/CAs", CAs);
}
I have checked that DeleteCA is really removing the correct item. The modified list of CAs passed to PartialView no longer contains the deleted item.
Something weird happens when the partial view is rendered. The number of items in the list is reduced but it is always the last element that is removed from the list. The rendered items does not correspond to the items in the list/model sent to PartialView.
In the usercontrol file (ascx) I'm using both Model.CAList and lambda expression m => m.CAList.
How is it possible for the usercontrol to render stuff that is not in the model sent to PartialView?
Thanx
Andreas
It sounds like the ModelState is the trouble here, as you bind to CAs the ModelState save this values in the background as Attempted Values, so its true the object is no longer present at the Model, but the ModelSate still have the values of the deleted object. You can try a:
ModelState.Clear();
To remove all those old values.
Check in firebug what the response realy is. This way you can see if you have a serverside problem or it is a jquery issue.