NullReferenceException MVC4 C# Most likely beginner fail - c#

I have been following
http://pluralsight.com/training/Courses/TableOfContents/mvc4-building
to learn some MVC C# for my Company, btw completely amazing Video.
I am populating a View with a SQL source.
In Debug I can definitely tell all my connections work, and I get to my foreach loop that should display all the data in that table
On my #Foreach( var item in Model ) it throws the NullRefException on my Model... here's the code I have
this is my complete view
#model IEnumerable<OilNGasWeb.ModelData.Clients>
#{
ViewBag.Title = "CLS-Group";
}
#foreach(var item in Model)
{
<div>
<h4>#item.Client</h4>
<div>#item.Address</div>
<div>#item.City</div>
<div>#item.State</div>
<div>#item.Zip</div>
<div>#item.ContactName</div>
<div>#item.ContactEmail</div>
<div>#item.County</div>
<div>#item.Authorized</div>
<hr />
</div>
}
So I'm thinking it is instantiated here
#model IEnumerable<OilNGasWeb.ModelData.Clients>
but just incase I was wrong maybe it's instantiated in the Home controller in the Index Action?
public ActionResult Index()
{
var Model = _db.Clients.ToList();
return View();
}
Please help me figure out why it's throwing this exception thanks. I wouldn't think you needed more code. but if you do let me know what M , V , C to post for you, as said above the data part works great.

public ActionResult Index()
{
var model = _db.Clients.ToList();
return View(model);
}
You need to pass the model to the view, otherwise it will be null.

Related

Passing a View Model within a URL.Action

I'm trying to pass a view model to my controller.
#if (User.IsInRole("Customer"))
{
<input type="button" class="btn btn-danger" value="Rent Car" onclick="location.href='#Url.Action("PassingCar", "Bookings", new { id = item.VehicleID, Model = Model.Booking })'" />
}
I'm using a dynamic model so I can use both Vehicle and Booking in this view.
When the code gets to my controller the ID has been passed over but the data in the ViewModel is gone.
public ActionResult PassingCar( int id, CreateBookingViewModel createdModel)
{
///Checks that Vehicle exists in DB and v property is not null
if (v == null)
{
return HttpNotFound();
}
else
{
/// sets the Vehicle attribute of the BookingViewModel to vehicle passed over
createdModel.Vehicle = v;
}
return RedirectToAction("Create", "Bookings");
}
If anybody has an idea what i'm doing wrong it would be greatly appreciated.
Can you post the text of the URL you end up at?
But at a guess, you might want to replace Model = Model.Booking with Model = JSON.Encode(Model.Booking)
Oh. And another probability. You name the parameter "Model" in the Url Action, but "createdModel" in the method signature.
I discoverer my problem so I'm gonna post an answer for anyone encountering the same thing, and find this thread.
Because both of the names in the URL Action where called Model, this would create a brand new ViewModel passed to the view. This was due to the fact in my View, the model was a dynamic model I created so the Object that was being created was anew ExpandoObject.
A solution would of been to cast the ExpandoObject to the correct type, but I discovered a different way to solve my specific problem just using TempData. Either way would of worked.

Pass model into template from Surface Controller

Is there a way I can pass in a populated object or list into a template / view from a surface controller in Umbraco 7?
Sounds like a good spot to use ViewData. There isn't much info in the question so I am kind of winging it here, but something like this...
// your surface controller
public ActionResult SubmitForm(YourFormModel model)
{
if (ModelState.IsValid) {
var submitResults = ResultsOfYourCode();
ViewData["submitResults"] = submitResults;
return RedirectToCurrentUmbracoPage();
}
}
// your view
#{
var submitResults = (submitResultsType)#ViewData["submitResults"];
}
<p>#submitResults.Property1</p>
This is totally untested and is just off the top of my head to give you an idea.

Tag Helper forms: asp-for not working as expected

Thanks for the help so far. I've worked to make sure everything else works so I can focus on this problem. I'm still convinced it'll be an easy fix once we've cracked it. I have the following code, sorry I changed it so much, I had to start again after I made a real mess of the last one without taking a backup.
public IActionResult Index()
{
if(IndexModel.GlobalTasks == null)
{
IndexModel initModel = new IndexModel();
initModel.AllTasks = InitList();
initModel.EmptyTask = new ToDoTask();
IndexModel.GlobalTasks = initModel.AllTasks;
}
IndexModel model = new IndexModel();
model.AllTasks = IndexModel.GlobalTasks;
model.EmptyTask = new ToDoTask("");
return View(model);
}
//Create Task
public IActionResult Create(ToDoTask indexModel)
{
IndexModel.GlobalTasks.Add(indexModel);
return RedirectToAction("Index");
}
And:
#model DE.Models.IndexModel
<h2>To Do List</h2>
<form asp-action="Create">
<input asp-for="EmptyTask" value="#Model.EmptyTask" />
<input asp-for="EmptyTask.TaskDetails" placeholder="New Task" />
<button type="submit">Add Task</button>
</form>
The good news is this creates a new ToDoTask. So the Controller code must be pretty close to spot on. The problem is the View is passing null details to the controller, so I'm getting an empty Task, which isn't what I want.
Any ideas?
Using Tag Helper forms:
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<section >
<input type="text" asp placeholder="Title" asp-for="MyWork.Title"/>
</section >
Your controller action expects a ToDoTask object while your view uses a TaskViewModel object.
Try using the same type in both of them.
In your Create() method you need to instantiate the ToDoTask object, I think. So try this:
[HttpPost]
public IActionResult Create(ToDoTask newTask)
{
newTask = new ToDoTask();
return RedirectToAction("Index");
}
You may also need to return the ToDoTask object.

.NET MVC 4 - Multiple "actions" on same Controller, how?

I'm pulling my hair out over this one and I'm looking for guidance before I start fudging together my own approach.
Here's what I've got:
View snippet
<td>#Html.ActionLink("More Details", "Index", new { id = product.ProductId })</td>
<td>#Html.ActionLink("Compare", "Compare", new { id = product.ProductId, compare = true })</td>
Controller snippet
public ActionResult Index(FormCollection values)
{
// Does stuff, works
}
public ActionResult Index(int productId)
{
// Does stuff, works
}
Now, here lies my problem. The Index functions are both taken now, from the POST to the form, and the "More Details" ActionLink being clicked. This works fine.
Now I want "Compare" to be functional, in which I want on the same page and will hold a list of compared products, which is fine. But how do I get that Compare functionality on the same View/Page?!
I've tried:
public ActionResult Compare(int productId)
{
}
But obviously that doesn't work as it requires a Compare.cshtml, which I don't want to happen. I want it to be modify my ViewModel and return it with newly Compared products, so I'd be able to do this from my original View:
#foreach(var products in Model.ComparedProducts)
The only way I can see me doing this is "fudging it" to have:
public ActionResult Index(int productId = 0, bool compare)
{
}
Which could become unruly with lots of functionality on the same page.
Surely there's something obvious I'm missing here?
Oh, and the AjaxLink options isn't right for me, as this is part of the site that has to work via postbacks (Progress Enhancement and all that jazz).
I think you return an ActionResult by calling return View(model), is that right? Without naming a view explicitly, the MVC resolving mechanism looks for views with the same name as the action, in your case "Compare.cshtml".
If you change your call to return View("Index", model) you will be using the Index.cshtml view regardless of the action name.
Is that what you were looking for?
An action in MVC does not require a corresponding View. It can return any view by supplying a name parameter to the View() function - see http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.view%28v=vs.98%29.aspx for details.
You can in your compare function do all the logic required and redirect back to the index action or any other that display the page as needed using RedirectToAction().

MVC presistent Model

In a MVC 3 application i need to be able to part creation view in 2 different parts, because of some folder creation logic.On first view i have a textbox with Project Name, on click of next button i need to create folder for that project, and i need a way to get that project name folder on my next view in some way. Right now i press next and i loose project Name, and i cant get it again.
On internet there are plenty of places where they implement it the same way, but i cant figure out how to do that.
Any solutions on how to presist model?
You could use a hidden field in the second view that will contain the project name that was entered in the first view. That way when you submit this second form you will get the project name and the project folder.
Another possibility is to store the value that was entered in the first view somewhere on the server (database, session, ...)
UPDATE:
As request in the comments section here's an example using a hidden field.
First view:
#model FirstStepViewModel
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.ProjectName)
<button type="submit">OK</button>
}
then a controller action to which this first step will be submitted:
[HttpPost]
public ActionResult Foo(FirstStepViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
return RedirectToAction("Bar", new { projectname = model.ProjectName });
}
and then you will have a second controller action that will serve the second view:
public ActionResult Bar(FirstStepViewModel firstStep)
{
var model = new SecondStepViewModel
{
ProjectName = firstStep.ProjectName
};
return View(model);
}
you will then have a corresponding view:
#model SecondStepViewModel
#using (Html.BeginForm())
{
#Html.HiddenFor(x => x.ProjectName)
#Html.EditorFor(x => x.ProjectFolder)
<button type="submit">OK</button>
}
which will post to the final action:
[HttpPost]
public ActionResult Bar(SecondStepViewModel model)
{
// here you will get both model.ProjectName and model.ProjectFolder
...
}
You could also load all parts of the form at once, and then use a tabbed layout (e.g., jQuery UI Tabs) and submit the entire form at the last step.

Categories