DropDownListFor getting null value and appear ArgumentNullException - c#

I attempting to do is passed a viewData from controller to view and display it in drop down list.
I wish to add the selected Id pass into m.movie_type_id.
But I keep on getting ArgumentNullException. Detailed information state that the Value cannot be null.
Below is how I was code and getting error exception.
<%=Html.DropDownListFor(m=> m.movie_type_id,new SelectList((IEnumerable)ViewData["MT"],"Id","Type")) %>
In Controller
public ActionResult AddMovie()
{
ViewData["MT"] = db.MovieType.ToList();
return View();
}
[HttpPost]
public ActionResult AddMovie()
{
return view();
}
Current stage is just for testing purpose. Since the error occur during the data pass back to the controller, I wish to fix it before i proceed.
Where did I done wrong?

Please make sure that viewdata is filled by some collection and passed into your view like
public ActionResult MyAction()
{
ViewData["MT"] =YourIEnumerableCollection() //Code to get the collection
return view(model);
}
EDIT
I think you are getting this in POST scenario, you need to pass the ViewData in POST too like
[HttpPost]
public ActionResult AddMovie()
{
ViewData["SQ"] = db.MovieType.ToList();
return View();
}

Related

Post model to an MVC ActionResult

I have an ASP.net application with a [HttpGet] for a view an ActionResult named 'Create' on a Controller called Students
My 'Student' is then posted to the following controller.
[HttpPost]
public async Task<ActionResult> Create(Student student)
{
Student.Add(student);
if (ModelState.IsValid)
{
var result = db.Students.Add(student);
await db.SaveChangesAsync();
return Details(result);
}
return View(new CreateStudent());
}
return Details(result); is the line I'm interested in.
Previously I had RedirectToAction where I passed in the result. Id property and used a GET request to query a database.
But, I'm not wanting to have a URL like 'students/details/id=123' Or 'students/details/123' I want to Post my model to the controller 'students/details'
var result is a single 'Student'and my 'Details' ActionResult looks like this:
[HttpPost]
public async Task<ActionResult> Details(Student student)
{
//
}
but return Details(result); doesn't work, I receive an error message stating:
'The model item passed into the dictionary is of type 'LinkApp.Models.Student', but this dictionary requires a model item of type 'LinkApp.Models.DTOs.CreateStudent'.'
But I believe this is because my URL never goes to '/Students/Details', my URL still shows '/Students/Create'
Any help is appreciated. And again, if it's not clear, please ask for any clarity
Thanks
EDIT DUE TO ME NOT BEING VERY CLEAR ;)
So I'm a little bit confused with what you're trying to achieve.
Here is what I've gathered: You want to POST the data. Right now you have a GET method. You can think of a GET method like something that retrieves, and a POST as something that gives.
So your GET method should not be trying to POST anything.
Your GET method should looks like it should be a POST since you're trying to "give" the data to something, not get the data.
[HttpPost]
public async Task<ActionResult> Create(Student student)
{
Student.Add(student);
if (ModelState.IsValid)
{
var result = db.Students.Add(student);
await db.SaveChangesAsync();
return View("Details", result);
}
return View(); //You should add a property to the model called ErrorMessage or something like that, then you could do student.ErrorMessage = "Model state was not valid";, then you could do return View(student); and in the view you could do something like #if (Model.ErrorMessage != null) { #Html.DisplayFor(m=>m.ErrorMessage); }
}
This is what your post should look like, you're saving the Student model to the database and returning to a view.
Now your GET should just be something like this:
[HttpGet]
public ActionResult Create()
{
return View();
}
Edit:
If you wanted your post to do the error message I left in the comment above you would just do this right above the second return View();
student.ErrorMessage = "Model state was not valid;" //Or whatever you want to say
return View(student);
Then in your view you would have something like this:
#if (student.ErrorMessage != null)
{
#Html.DisplayFor(m => m.ErrorMessage);
}

Razor form not passing back to controller method

I am trying to pass a textbox's text back to a method in my controller, but the data is not being passed in the parameter
I am genuinely confused, i'm following another example but i'm getting a different result, ie - my method behaving as if no parameter is passed
Code
public ActionResult Index(string searchString)
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
var listOfAnimals = db.Animals.ToList();
if (!String.IsNullOrEmpty(searchString))
{
listOfAnimals = listOfAnimals.Where(a => a.AnimalName.ToLower().Contains(searchString.ToLower())).ToList();
}
return View(listOfAnimals);
}
and here is my razor form from my view page
#using(Html.BeginForm("Index", "Home"))
{
#Html.TextBox("searchString")
<input type="submit" id="Index" value="Index" />
}
Can anybody spot why this isn't working?
If more code is needed, please let me know but i think the issue is isolated to here
You code is correct.
Since you didn't add [HttpGet] or [HttpPost] before index method.
This method was called twice.
The first call ran when producing the page with form via url http://server/Home/Index. This call was an http get and searchString mapped from URL was null, which is correct.
The second call ran when you clicked submit button. Correct value would be mapped by MVC correctly.
You need to have 2 Index actions (two methods), one without decorations (GET verb) and another one decorated with HttpPost (POST verb). Basically, when you go to the index page, the GET action is executed. When you submit the form, a POST request is executed and the Index decorated with HttpPost is executed.
// GET
public ActionResult Index() { ... }
// POST
[HttpPost]
public ActionResult Index(string searchString) { ... }
Francisco Goldenstein wrote the recommended way. It means you can have two Index() actions:
// for GET
public ActionResult Index() { ... }
// for POST
[HttpPost]
public ActionResult Index(string searchString) { ... }
However it is possible to have one Index() method for handling both (GET and POST) requests:
public ActionResult Index(string searchString = "")
{
if(!string.IsNullOrEmpty(searchString)
{ /* apply filter rule here */ }
}
You wrote, your code is not working. Do you mean, your action method is not requested after click on the button? Consider to allow empty value Index(string searchString = "")
If your action method is fired but variable is empty, check the name on the View() side. Textbox must not be disabled, of course.

ASP.NET MVC HttpPost posting null model

Form posts from webpage MakeBooking to FinalBooking to ascertain certain information such as number of guests, so the FinalBooking page can give you enough textboxes to input guest information for all guests required.
When in debug mode, both models in MakeBooking post are populated. After post, in FinalBooking, model is null.
[HttpPost]
public ActionResult MakeBooking(BookingModel model)
{
return RedirectToAction("FinalBooking", "Booking", new { model = model });
}
public ActionResult FinalBooking(BookingModel model)
{
return View(model);
}
Any info would be appreciated.
It should work
return RedirectToAction("FinalBooking", "Booking", model);
You can not pass a model with RedirectToAction like that. you need to use either TempData or Session to transfer the model object between your calls.
RedirectToAction method returns an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action.
The below example shows how to transfer data using TempData.
[HttpPost]
public ActionResult MakeBooking(BookingModel model)
{
TempData["TempBookingModel"]=model;
return RedirectToAction("FinalBooking", "Booking");
}
public ActionResult FinalBooking()
{
var model= TempData["TempBookingModel"] as BookingModel;
return View(model);
}
Internally TempData is using Session as the storage mechanism.

return view doesn't run controller code mvc

I have a problem with "return view()" that doesn't excute code in my controller.
I have a controller with this code:
public class BrokerController : BaseController
{
public ActionResult BestallMaklarBild()
{
return View(new BestallMaklarBildViewModel());
}
[HttpPost]
public ActionResult BestallMaklarBild(FormCollection collection)
{
try
{
//Some code
return View("MaklarBildBestalld",new MaklarBildBestalldViewModel());
}
catch
{
return View(new BestallMaklarBildViewModel());
}
}
public ActionResult MaklarBildBestalld()
{
//Some code
return View(new MaklarBildBestalldViewModel());
}
}
When I post to my controller "BestallMaklarBild" and then try to return the view("MaklarBildBestalld",new MaklarBildBestalldViewModel()), the code in "MaklarbildBestalld" doesn't execute. So when the model is returned to the view it doesn't contain any data, and cause my view leaving me with an error saying that the model.something = null when I try to output some data to the view.
Don't know what Im doing wrong.
That's normal. You need to redirect to this controller action if you want the code to execute:
try
{
//Some code
return RedirectToAction("MaklarBildBestalld", new { id = "some id" });
}
catch
{
return View(new BestallMaklarBildViewModel());
}
and now the action will execute:
public ActionResult MaklarBildBestalld(string id)
{
//Some code
return View(new MaklarBildBestalldViewModel());
}
Here's the correct workflow:
The BestallMaklarBild POST controller action is invoked and passed a view model
This controller action attempts to persist the model and redirects in case of success to the MaklarBildBestalld controller action passing it an unique identifier as query string of this model so that this action is able to retrieve the model back. In case of failure it simply redisplays the form so that the user can fix the errors he did, or see the error message that there was a problem processing his request.
You must ensure that your view has the model in your parameters as a generic type.

ASP.Net MVC Object Reference in Edit View when using DropDownListFor()

This question is related to another I ask recently, it can be found here for some background information.
Here is the code in the Edit ActionResult:
public virtual ActionResult Edit(int id)
{
///Set data for DropDownLists.
ViewData["MethodList"] = tr.ListMethods();
ViewData["GenderList"] = tr.ListGenders();
ViewData["FocusAreaList"] = tr.ListFocusAreas();
ViewData["SiteList"] = tr.ListSites();
ViewData["TypeList"] = tr.ListTalkbackTypes();
ViewData["CategoryList"] = tr.ListCategories();
return View(tr.GetTalkback(id));
}
I add lists to the ViewData to use in the dropdownlists, these are all IEnumerable and are all returning values.
GetTalkback() returns an Entity framework object of type Talkback which is generated from the Talkback table.
The DropDownListFor code is:
<%: Html.DropDownListFor(model=>model.method_id,new SelectList(ViewData["MethodList"] as IEnumerable<SelectListItem>,"Value","Text",Model.method_id)) %>
The record I am viewing has values in all fields. When I click submit on the View, I get an Object reference not set to an instance of an object. error on the above line.
There are a number of standard fields in the form prior to this, so the error is only occurring on dropdown lists, and it is occurring on all of them.
Any ideas? This is my first foray in to MVC, C#, and Entity so I am completely lost!
If you have [HttpPost] method like that
[HttpPost]
public ActionResult Edit(Talkback model)
{
//Do something with model
return View(model);
}
You have to fill ViewData again. If you don't do it, you'll have Object reference not set to an instance of an object errors.
The best thing to do would be to follow POST-REDIRECT-GET patter and do it like that:
[HttpPost]
public ActionResult Edit(Talkback model)
{
//Do something with model
return RedirectToAction("Edit", new { id = model.id });
}
You'll have ViewData filled again by [HttpGet] method.

Categories