Getting a single object from SQL Server to a view - c#

I have a an object of type Picture that contains a List Comments see source code here http://pastebin.me/21148a93065bddb7302e160f5a0ac1fb
I then want to take an Picture.ID and show the image that has that unique ID from my database
So I made a ActionResult Comment in my GalleryController http://pastebin.me/21148a93065bddb7302e160f5a0acb02 with a HttpGet
I then have this view that should display the requested image and the comments in its list http://pastebin.me/21148a93065bddb7302e160f5a0acb02
But I am not sure if its the List that is not initialized or if I am just doing it wrong but I get an error
Server Error in '/' Application.
Object reference not set to an
instance of an object.
Description: An
unhandled exception occurred during
the execution of the current web
request. Please review the stack trace
for more information about the error
and where it originated in the code.
Exception Details:
System.NullReferenceException: Object
reference not set to an instance of an
object.
Source error: http://pastebin.me/21148a93065bddb7302e160f5a0ad965

Let's examine the Action method in question. First of all, I see this and this should almost never exist:
catch
{
}
So if an exception was thrown, you're just swallowing it up and will never know about it. This would result in returning a view with no model passed in, thus the model referenced in your strongly-typed view is null. This seems like a very good possibility of what's happening.
Also, why do you keep overwriting ViewBag.Picture inside your foreach loop? Is that really what you intended to do?
Hopefully this will get you on the right path and you'll quickly get to the underlying issue.

as I cant get it to only parse a single object (And I know there will always be max one result as it searches in the database on the primary key)
So my code is now
[HttpGet]
public ActionResult Comment(string ID)
{
int id = Convert.ToInt32(ID);
if (ID != null)
{
try
{
var model = from r in _db.Gallery
where r.ID == id
select r;
return View(model);
}
catch
{
}
}
return View();
}
And
#model IEnumerable<firstweb4.Models.Picture>
#{
ViewBag.Title = "Comment";
}
#if (Model != null)
{
foreach (var item in Model)
{
<img src="#item.Path" alt="#item.Title" width="250px" />
<table>
<tr>
<th>
Posted by
</th>
<th>
Comment
</th>
<th>
Posted on
</th>
</tr>
#foreach (var comment in item.PictureComments)
{
<tr>
<td>
#comment.Auther
</td>
<td>
#comment.Text
</td>
<td>
#comment.PostedTime
</td>
</tr>
}
</table>
}
}
So I itterate through a the singleitem collection I parse and it now works.

Related

Foreach Loop in Razor Component causes await to fail

I'm new to Blazor and .NET 6, but I am working on a small app. I have LiteDB storing data on the backend, and my Razor component is fetching it. The problem is that, while 80% of the time it works as expected, the other 20% of the time the data gets populated as null in the Razor component before the database call has even processed. When debugging this, I see the code get to the database call in the backend, then it jumps back to the frontend Razor component which now has a null object, and then it jumps back to the backend where the database call has now been completed. The page populates from the null object though, so the data is not there. I get an error in the console, but it's just stating that the object was not set to an instance of an object at a foreach loop in my code. Here's my code:
#page "/origin"
#page "/origin/{id:int}"
#inject HttpClient http
#if (id == null)
{
<PageTitle>Origin Not Found</PageTitle>
<h3>Origin Not Found</h3>
}
else
{
<PageTitle>Origin: #origin.Name</PageTitle>
<h3>Origin: #origin.Name</h3>
<table class="table">
<tbody>
<tr>
<td>Description: </td>
<td>#origin.Description</td>
</tr>
<tr>
<td>Starting Health: </td>
<td>#origin.StartingHealth</td>
</tr>
<tr>
<td>Ground Movement Speed: </td>
<td>#origin.GroundMovementSpeed</td>
</tr>
#foreach(var stat in #essences)
{
<tr>
<td>Essence Increase Option: </td>
<td>#stat</td>
</tr>
}
<tr>
<td>Origin Benefit: </td>
<td>#origin.OriginBenefit</td>
</tr>
</tbody>
</table>
}
#code {
[Parameter]
public int id { get; set; }
private Origin origin = new();
private List<Essence> essences = new();
protected async override Task OnInitializedAsync()
{
var result = await http.GetFromJsonAsync<Origin>($"/api/origin/{id}");
if(result != null)
{
origin = result;
essences = result.EssenceIncreaseOptions;
}
}
}
Now if I remove the foreach loop (and the essence information I want there), then the code works 100% of the time. So there's something about that foreach loop that's causing it to fail 20% of the time, but I'm just not sure what. Any help would be appreciated. Thanks in advance.
In the posted code, the only point in the foreach(var stat ...) that could yield an NRE is <td>#stat</td>
So your Essence class probably has an override ToString() that causes the null de-reference.
What you can do is put a conditional check before the #foreach loop and when essences is null show some message saying loading etc, also, put StateHasChanged() after completion of fetching of data.
#if(essences.Count>0)
{
#foreach(var stat in #essences)
{
<tr>
<td>Essence Increase Option: </td>
<td>#stat</td>
</tr>
}
}
else {loading data}
and
protected async override Task OnInitializedAsync()
{
var result = await http.GetFromJsonAsync<Origin>($"/api/origin/{id}");
if(result != null)
{
origin = result;
essences = result.EssenceIncreaseOptions;
StateHasChanged();
}
}

how to loop a service object in the view in MVC

I have the following code:
#foreach (var item in #ViewBag.list)
{
<span>#item.Id </span>
}
The ViewBag gets the data from a service that contains a class that gets the data from a database, but I'm getting a null exception error since the ViewBag is null because a user has to first enter a date to be able to get the list of ids.
public async Task<ActionResult> plan_post(DateTime dateselected)
{
DateTime date = dateselected;
var plan = await _ps.PlanbyDate(date, date);
ViewBag.list = plan;
return View();
}
I'm a student doing an internship can you help me with this?
this is the error:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Fo fixed your problem you must debugging your plan object may be null !!!
But you must check if viewbag null not render foreach
if(ViewBag.list != null)
{
//write for each in here
}
You have more options for pass Model to view.
I recommend you use pass with View function
retune View(plan)
But must declaration datatyoe model in top page view
#model YourDataType

Need help passing file from view to controller

I am allowing users to upload a file from the view which will eventually be passed to the model through controller actions. However, there is a particular situation that is giving me trouble.
I have the followong ViewModel that I'm passing to the view:
public class RegisterStudentViewModel
{
public Login loginViewModel;
public Person personViewModel;
public PersonResume personResViewModel;
}
When the form is submitted, I use some validation logic to make sure the fields entered were applicable, and if any of the validation fails, I send the ViewModel that I'm using back to the view, to make sure that the fields that had information entered correctly are stored. Before this though, I have also made sure that the file uploaded is binded to the model that it belongs to, like this:
if (res != null)
{
PersonResume resumeViewModel = createResume(res, personModel);
vm.personResViewModel = resumeViewModel;
}
SetUpView(vm, da);
result = View(vm);
}
so that when the validation fails but the resume wasn't one of the fields that failed and I want to display the uploaded resume, I can use the following code in my view:
#if (Model.personResViewModel != null && Model.personViewModel.id == 0)
{
<th class="editAddLabel">
#Html.LabelFor(model => model.personResViewModel.ResumeFileName, "Resume File Name")
</th>
<td>
#Html.ActionLink("View your resume", "linkDownload", "Student", new { id = Model.personViewModel.id, resume = Model.personResViewModel}, null)
</td>
}
to pass to the following controller method that will allow the link to be downloaded:
public FileResult linkDownload(int id, PersonResumeViewModel resume)
{
DataAccess da = new DataAccess();
PersonResume displayResume = new PersonResume();
if (id != 0)
{
displayResume = da.getPersonResumeByID(id);
}
else
{
displayResume.ResumeData = resume;
}
//some more code that downloads file
}
I know that in the view, the personResViewModel is not null, but when I look at the controller method, it is null and I can't do anything with it. Am I not passing my argument in correctly?

ViewModel Property Null in Post Action

This is now fixed. A combination of Ish's suggestion below plus adding calls to #HiddenFor in the view resolved the problem.
I have an ASP.NET MVC 5 web application where users can mark a defect as resolved. I want to display a list of potentially related defects, with check-boxes that users can tick to indicate that yes, this is the same defect, and should also be marked as resolved.
So I have a View Model with a property that is a collection, each member of which contains a defect object property and Boolean IsSameDefect property. This all works fine in the GET action method and in the view. I can display the related defects and tick the boxes.
The problem arises in the POST action when I want to update the data. At this point the property (the collection of potentially related defects) is null. I'm having a hard time trying to figure out how to pass this data back to the controller?
Code as requested ...
// GET: /DefectResolution/Create
public ActionResult Create(int ciid)
{
int companyId = User.CompanyID();
DefectResolutionCreateViewModel drcvm = new DefectResolutionCreateViewModel(ciid, companyId);
return View(drcvm);
}
// POST: /DefectResolution/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(DefectResolutionCreateViewModel drcvm)
{
DefectResolutions currentResolution = drcvm.DefectResolution;
currentResolution.CreatedOn = System.DateTime.Now;
currentResolution.UserID = User.UserID();
if (ModelState.IsValid)
{
unitOfWork.DefectResolutionRepository.Insert(currentResolution);
if (currentResolution.ResolutionStatusID == 2)
{
//code breaks here as drcvm.RelatedUnresolvedDefects is null
foreach (var relatedDefect in drcvm.RelatedUnresolvedDefects)
{
if (relatedDefect.IsSameDefect)
{
DefectResolutions relatedResolution = new DefectResolutions();
relatedResolution.ChecklistID = relatedDefect.RelatedChecklist.ChecklistID;
relatedResolution.CreatedOn = System.DateTime.Now;
relatedResolution.ResolutionNote = currentResolution.ResolutionNote;
relatedResolution.ResolutionStatusID = currentResolution.ResolutionStatusID;
relatedResolution.UserID = User.UserID();
}
}
}
unitOfWork.Save();
return RedirectToAction("Index", new { ciid = currentResolution.ChecklistID });
}
return View(drcvm);
}
In the view ...
#model Blah.ViewModels.DefectResolution.DefectResolutionCreateViewModel
#{
ViewBag.Title = "Create Defect Resolution";
var relatedDefects = Model.RelatedUnresolvedDefects;
}
... and later in the view ...
#for (int i = 0; i < relatedDefects.Count(); i++ )
{
<tr>
<td>
#Html.EditorFor(x => relatedDefects[i].IsSameDefect)
</td>
</tr>
}
I followed Ish's suggestion below, and modified the code to refer to Model.RelatedUnresolvedDefects directly instead of using a variable as I had been doing. This does get me a bit further. The view model's RelatedUnresolvedDefects property is no longer null. But only RelatedUnresolvedDefects.IsSameDefect has a value. RelatedUnresolvedDefects.RelatedChecklist is null. Here's the controller code again showing where it now breaks ...
// POST: /DefectResolution/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(DefectResolutionCreateViewModel drcvm)
{
DefectResolutions currentResolution = drcvm.DefectResolution;
currentResolution.CreatedOn = System.DateTime.Now;
currentResolution.UserID = User.UserID();
if (ModelState.IsValid)
{
unitOfWork.DefectResolutionRepository.Insert(currentResolution);
if (currentResolution.ResolutionStatusID == 2)
{
//prior to change, code used to break here
foreach (var relatedDefect in drcvm.RelatedUnresolvedDefects)
{
if (relatedDefect.IsSameDefect)
{
DefectResolutions relatedResolution = new DefectResolutions();
//code now breaks here because relatedDefect.RelatedChecklist is null
relatedResolution.ChecklistID = relatedDefect.RelatedChecklist.ChecklistID;
relatedResolution.CreatedOn = System.DateTime.Now;
relatedResolution.ResolutionNote = currentResolution.ResolutionNote;
relatedResolution.ResolutionStatusID = currentResolution.ResolutionStatusID;
relatedResolution.UserID = User.UserID();
}
}
}
unitOfWork.Save();
return RedirectToAction("Index", new { ciid = currentResolution.ChecklistID });
}
return View(drcvm);
}
Without knowing your code.I suggest you to use for loop instead of foreach while rendering the defects in View (.cshtml).
Editing Answer based on your code.
Following statement in the view creating problem
var relatedDefects = Model.RelatedUnresolvedDefects;
You should directly iterate over the Model.RelatedUnresolvedDefects property in the loop.
#for (int i = 0; i < Model.RelatedUnresolvedDefects.Count(); i++ )
{
<tr>
<td>
#Html.EditorFor(x => Model.RelatedUnresolvedDefects[i].IsSameDefect)
</td>
</tr>
}

In MVC 4 How do I Add multiple Collections to a session?

I'm using MVC 4 with Razor Syntax to create a collection based on a class that was created using scaffolding (Database first based development) and I can add the first collection to the Session and return it to the Index view and display it on the page.
When I attempt to add a second collection to the Session Variable it gives me a error.
Unable to cast object of type
'System.Collections.Generic.List`1[EagleEye.Models.tblTask]' to type
'EagleEye.Models.tblTask'.
What am I doing wrong - how do I add 2 collections to the session?!
Index.cshtml (My Index view using Razor syntax)
#model List<myApp.Models.tblTask>
<table>
#{
foreach (var tblTask in Model)
{
<tr>
<td>
TaskName: #tblTask.Name
</td>
<td>
Desc: #tblTask.Description
</td>
<td>
Schedule: #tblTask.Freq #tblTask.FreqUnit
</td>
<td>
Reocurring?: #tblTask.ReocurringTask.ToString()
</td>
</tr>
}
}
</table>
Here's the "ActionResult" portion of the code from my HomeController.cs:
[HttpPost]
public ActionResult CreateTask(tblTask newTask)
{
var TaskCollection = new List<tblTask>();
if (Session["TaskCollection"] != null)
{
TaskCollection.Add((tblTask)Session["TaskCollection"]);
}
TaskCollection.Add(newTask);
Session["TaskCollection"] = TaskCollection;
return RedirectToAction("Index");
}
public ActionResult Index()
{
var TaskCollection = new List<tblTask>();
if (Session["TaskCollection"] != null)
{
TaskCollection = (List<tblTask>)Session["TaskCollection"];
}
return View(TaskCollection);
}
When I add the first entry it works fine and shows up on my index view. When I try to add the second collection of tasks, it tells me:
Unable to cast object of type
'System.Collections.Generic.List`1[EagleEye.Models.tblTask]' to type
'EagleEye.Models.tblTask'.
I've been fighting this for a few days now and have been developing for a while, but am just beginning to learn the power of asking questions when I'm stumped (instead of just continuing to beat my head against the wall until something caves in (often my head), so if my question is not well formed, please let me know.
Thanks!
Dan
Because, inside your if condition, you are casting the Session["TaskCollection"](which is a collection of tblTask to a single instance of tblTask.
This should work.
[HttpPost]
public ActionResult CreateTask(tblTask newTask)
{
var TaskCollection = new List<tblTask>();
//Check whether the collection exist in session, If yes read it
// & cast it to the tblTask collection & set it to the TaskCollection variable
if (Session["TaskCollection"] != null)
{
TaskCollection= (List<tblTask>) Session["TaskCollection"];
}
if(newTask!=null)
TaskCollection.Add(newTask);
//Set the updated collection back to the session
Session["TaskCollection"] = TaskCollection;
return RedirectToAction("Index");
}
I finally see the light -- Note the change in the HomeController.cs "TaskCollection = (List)Session["TaskCollection"]; "
[HttpPost]
public ActionResult CreateTask(tblTask newTask)
{
var TaskCollection = new List<tblTask>();
if (Session["TaskCollection"] != null)
{
//Here is the line that changed -- the following line works~
TaskCollection = (List<tblTask>)Session["TaskCollection"];
}
TaskCollection.Add(newTask);
Session["TaskCollection"] = TaskCollection;
return RedirectToAction("Index");
}

Categories