i'm new at this tecnology and i'm having some trouble passing a list of an excel that i imported to my application, here's the code:
The problems is that the model in the Create Controller comes out null so i cant save into the database.
I can't save it before, in the uploadcomplete action because i intend to edit the values before save into the data base.
[HttpPost]
public ActionResult Index(HttpPostedFileBase excelFile)
{
if (excelFile != null)
{
//Save the uploaded file to the disc.
string savedFileName = Server.MapPath("~/UploadedExcelDocuments/" + excelFile.FileName);
excelFileHandler.ImportExcel(savedFileName, excelFile);
return RedirecToAction("UploadComplete",excelFileHandler.DataToEdit);
}
else { return RedirectToAction("Error", "Upload"); }
}
public ActionResult UploadComplete(List<Persona> DataToEdit) // This comes out null so i cant render the view now
{
return View();
}
[HttpPost]
public ActionResult UploadComplete(IEnumerable<ExcelImport.Persona> model)
{
return View();
}
public ActionResult Create(IEnumerable<ExcelImport.Models.Person> model)
{
using (ExcelimportDBTestEntities context = new ExcelimportDBTestEntities())
{
foreach (ExcelImport.Models.Person person in model)
{
Persona newPerson = new Person();
newPersona.Id = person.Id;
newPersona.Birthday= persona.Birthday;
newPersona.LastName= persona.LastName;
newPersona.Name = persona.Name;
context.Persons.AddObject(newPersona);
context.SaveChanges();
}
return View();
}
}
This is my View, there must be something wrong here
#model IEnumerable<ExcelImport.Models.Person>
#{
ViewBag.Title = "UploadComplete";
}
<h2>UploadComplete</h2>
#Html.BeginForm(){
<table>
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Last Name
</th>
<th>
Birthday
</th>
<th>
Options
</th>
</tr>
#foreach (var item in Model) {
#Html.HiddenFor(model => item)
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Birthday)
</td>
<td>
</td>
</tr>
}
</table>
<input type="submit" value="Upload!"/>
}
EDIT: i was tired yesterday so i put some... lets go whit "test" that i was doing by error, now this is what i really want to do. I got an Index View that upload the file and send to the post Index Controller, from there i want to send the list to my UploadComplete Controller, so i can render the UploadComplete View (the list comes out null), and in the post of that Action i want to send the model that i render in the UploadComplete View, to my create controller, so i can storage my data into the database. And as i said before i cant save it into the datebase in the index action becouse i intend to edit this data in the uploadcomplete view.
Thanks in advance, Regards.
As I can see in your code:
There is no [HttpPost] attribute
Form action is GET
Incorrect page rendering (hidden elemens)
Look at this example. It shows how lists could be binded on POST.
Related
I have the following code in the View.
<span>#Html.DisplayFor(modelItem => item.comments.comments_id)</span>
<span>#item.comments.comments_id</span>
The code below works if comments_id is not 0 or empty.
<span>#((item.comments.comments_id == 0) ? 0 : #item.comments.comments_id)</span>
If its 0 or empty I get
System.NullReferenceException: Object reference not set to an instance of an object.
The class contains this
public Nullable<int> comments_id { get; set; }
How can overcome this issue? thanks in advance.
---- EDit more code ---
public ActionResult Show()
{
var showItems = db.Projects.Include(p => p.Comments).ToList(); // INCLUDES ITEMS FROM BOTH TABLES
return View(showItems);
}
View
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ProjectName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comments.comments_id) // NOTICE this coming from a different table(Comments tbl).
</td>
<td>
<span>#((item.Comments.comments_id == 0) ? 0 : #item.Comments.comments_id) // HERE when item.Comments.comments_id has no contents it throws an error.
Create
</td>
</tr>
}
Someone posted something similar but I don't understand the answer.
http://forums.asp.net/t/1732717.aspx?How+to+check+if+model+property+is+empty+in+View+page
You need to use HasValue to check if a nullable variable has a value or not.
<span>#((item.comments.comments_id.HasValue) ? #item.comments.comments_id : 0)</span>
EDIT: Added Example
Your view code looks like it should work. Below is code I wrote to test your view. The lambda expression in your controller action won't be executed until it's used. So it's possible it's not executed until the view is rendered. This could cause a problem because the database connection may be closed by then. However, the call to ToList() should execute the lambda expression. So the problem is probably that item.Comments is null. You should test to see if it is as I did in my example.
Controller
public class HomeController : Controller
{
public class Project
{
public string ProjectName { get; set; }
public ProjectComments Comments { get; set; }
}
public class ProjectComments
{
public string Comments { get; set; }
public Nullable<int> comments_id { get; set; }
}
public ActionResult Index()
{
var showItems = new List<Project>();
showItems.Add(new Project()
{
ProjectName = "Project 1",
Comments = new ProjectComments() { Comments = "some comments", comments_id = 1 }
});
showItems.Add(new Project()
{
ProjectName = "Project 2",
Comments = new ProjectComments() { Comments = "more comments", comments_id = null }
});
return View(showItems);
}
}
View
#model IList<MvcApplication2.Controllers.HomeController.Project>
<table border="1">
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ProjectName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comments.comments_id)
</td>
<td>
<span>
#((item.Comments != null && item.Comments.comments_id.HasValue) ? #item.Comments.comments_id : 0)
Create
</span>
</td>
</tr>
}
</table>
I have been trying to create a simple portal to track logs from a mobile application. As such, I have used entity framework and MVC3 to help me with this. However recently I have been stuck when trying to retrieve the entity from the database.
Here is the Run class:
namespace LifestyleGuide.Models
{
[DataContract(IsReference = true)]
[KnownType(typeof(User))]
public partial class Run
{
[DataMember]
public string User_ID { get; set; }
[DataMember]
public System.DateTime Date { get; set; }
[DataMember]
public Nullable<int> Distance { get; set; }
[DataMember]
public Nullable<int> Duration { get; set; }
[DataMember]
public Nullable<int> Calories { get; set; }
[DataMember]
public virtual User User { get; set; }
}
}
User_ID and date are form a composite key where User_ID is a foreign key from the User table.
And the following is the "details" method from the controller:
public ActionResult Details(String id, DateTime date)
{
using (var db = new inspireEntities())
{
Run run = db.Runs.Find(id, date);
return View(run);
}
}
However, when i try to run it, the run object always appears as a null.
Any suggestions are greatly appreciated!
EDIT:
Here are is the view for the homepage.
#model IEnumerable<LifestyleGuide.Models.Run>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
<center>User ID</center>
</th>
<th>
<center>Date</center>
</th>
<th>
<center>Distance</center>
</th>
<th>
<center>Duration</center>
</th>
<th>
<center>Calories</center>
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.User_ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.Distance)
</td>
<td>
#Html.DisplayFor(modelItem => item.Duration)
</td>
<td>
#Html.DisplayFor(modelItem => item.Calories)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.User_ID, date = item.Date }) |
#Html.ActionLink("Details", "Details", new { id = item.User_ID, date = item.Date }) |
#Html.ActionLink("Delete", "Delete", new { id = item.User_ID, date = item.Date })
</td>
</tr>
}
</table>
The fields in the table are populated from the database directly and therefore should already exist.
Note: I have no problems with creating and accessing the run objects by using the view. The null run object only occurs when I directly do an insert statement into the database and when i try to retrieve it afterwards using the .find method as shown above.
Find() function returns first occurrence of matching item from the Collection which will be a single item that matched the condition. Since your view is strongly typed to IEnumerable<LifestyleGuide.Models.Run>, it's expecting a collection of Run objects not a single object.
You should modify your controller so that a collection (list) of Run objects are passed to the view. You could use WHERE clause like this :
public ActionResult Details(String id, DateTime date)
{
using (var db = new inspireEntities())
{
List<Run> run = db.Runs.Where(r=>r.Id==id && r=>r.Date==date);
return View(run);
}
}
Good luck :).
I realized the problem! Each entry to the database has a DateTime object with milliseconds while the query doesn't. I did a work-around to remove the milliseconds from all entries and it works!
I am terribly confused with MVC.
I don't have any code to show because i don't know how to do it.
I have an object
public class Name()
{
String name="balh"
String something="blah blah"
//this object works fine and doesn't look like this it has the appropriate get;set;
//use this as just an example
//please disregard this format
}
Now i have a
List<Name> list;//this just holds all of my objects
I need them to be passed to the View
I keep seeing something about models but i don't see it declared anywhere
How do i loop in the view to create something like this
<div> object1 string</div>
<div> object2 string</div>
<div> object3 string</div>
<div> object4 string</div>
<div> object5 string</div>
Your view would look like this, assuming you use your list as the model:
#model List<Name>
#foreach(var item in Model) {
<div> #item.name #item.something</div>
}
So your controller action method might be:
public ViewResult Index() {
// Somehow build list which is List<Name>
return View(list);
}
EDIT: You seem very new, so I recommend trying this tutorial: http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/intro-to-aspnet-mvc-3
Let's take an example.
Model:
public class MyViewModel
{
public string Name { get; set; }
public string Something { get; set; }
}
Controller:
public class HomeController: Controller
{
public ActionResult Index()
{
List<MyViewModel> model = new List<MyViewModel>();
model.Add(new MyViewModel { Name = "some name", Something = "something" });
model.Add(new MyViewModel { Name = "some other name", Something = "something else" });
return View(mdoel);
}
}
View (~/Views/Home/Index.cshtml):
#model IEnumerable<MyViewModel>
<table>
<thead>
<tr>
<th>Name</th>
<th>Something</th>
</tr>
</thead>
<tbody>
#foreach (vat item in Model)
{
<tr>
<td>#item.Name</td>
<td>#item.Something</td>
</tr>
}
</tbody>
</table>
use this code
#foreach (vat item in Model)
{
<tr>
<td>#item.Name</td>
<td>#item.Something</td>
</tr>
}
I have a view model that looks like this
public class ViewModelRound2
{
public Bid Bid { get; set; }
public bool SelectedForRound2 { get; set; }
}
I have a get action method that looks like this
public ActionResult Round2Manager(long id)
{
...
return View(round1Ring3Bids);
}
And a post method that looks like this (not implemented it yet)
[HttpPost]
public ActionResult Round2Manager(IEnumerable<ViewModelRound2> viewModelRound2)
{
return View(viewModelRound2);
}
My view looks like this
#for (var x = 0; x < Model.Count(); x++)
{
ViewModelRound2 viewModelRound2 = Model.ElementAt(x);
Bid bid = viewModelRound2.Bid;
string userName = #bid.User.Invitation.Where(i => i.AuctionId == bid.Lot.Lot_Auction_ID).First().User.User_Username;
<tr>
<td>
#userName
</td>
<td>
#bid.Bid_Value
</td>
<td>
#Html.EditorFor(c => c.ElementAt(x).SelectedForRound2)
</td>
</tr>
}
</table>
<div class="buttonwrapper2">
#Ajax.ActionLink("Select", "Round2Manager", new { viewModelRound2 = Model }, new AjaxOptions() { HttpMethod = "POST"} )
</div>
The page this renders, contains checkboxes per row in the rendered table and I want to be able to pass checked/unchecked values to the post method so that it can process them. The problem is that the viewModelRound2 parameter of the post method is always null. What is going on? How can I write this so that it does what I intend?
You should put all that HTML inside a <form>.
I have a simple question.
I have a model that looks like this:
public class AddEditChildProductModel
{
public string Name {get; set;}
public string Sku {get;set;}
........
public IEnumerable<AddEditPriceTierModel> PriceTiers {get;set;}
}
public class AddEditPriceTierModel
{
public int QtyStart {get;set;}
public int QtyEnd {get;set;}
........
}
My question is how do I edit the collection in the same view?
It would seem this would be very simple, maybe I am missing something.
Thanks!!
**Edit**
OK, so I used EditorTemplates, but now I am getting the following error:
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
This is my controller action:
public ActionResult EditChildProduct(AddEditChildProductModel model)
{
if (!ModelState.IsValid)
return PartialView("AddEditChildProduct", model);
ChildProduct childProduct = productService.GetChildProductByID(model.ID);
AutoMapper.Mapper.Map<AddEditChildProductModel, ChildProduct>(model, childProduct);
foreach (var tier in childProduct.PriceTiers)
{
tier.ChildProduct = childProduct;
}
UnitOfWork.Commit();
return ListChildProducts(model.ProductID);
}
Shouldn't this work, as I get the ChildProduct with the related PriceTiers collection and use AutoMapper to map the differences? I maintain hidden fields for the PK and FK fields on the PriceTier.
I am a bit confused.
You could use editor templates:
#model AddEditChildProductModel
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(x => x.Name)
#Html.EditorFor(x => x.Name)
#Html.ValidationMessageFor(x => x.Name)
</div>
<div>
#Html.LabelFor(x => x.Sku)
#Html.EditorFor(x => x.Sku)
#Html.ValidationMessageFor(x => x.Sku)
</div>
<table>
<thead>
<tr>
<th>QtyStart</th>
<th>QtyEnd</th>
</tr>
</thead>
<tbody>
#Html.EditorFor(x => x.PriceTiers)
</tbody>
</table>
<input type="submit" value="OK">
}
and then define the editor template which will be rendered for each element of the PriceTiers list (~/Views/Shared/EditorTemplates/AddEditPriceTierModel.cshtml) - the name and location of the editor template is important. You could also put it in ~/Views/SomeController/EditorTemplates/AddEditPriceTierModel.cshtml if the editor template is specific only for a given controller:
#model AddEditPriceTierModel
<tr>
<td>
#Html.LabelFor(x => x.QtyStart)
#Html.EditorFor(x => x.QtyStart)
#Html.ValidationMessageFor(x => x.QtyStart)
</td>
<td>
#Html.LabelFor(x => x.QtyEnd)
#Html.EditorFor(x => x.QtyEnd)
#Html.ValidationMessageFor(x => x.QtyEnd)
</td>
</tr>
and now your POST controller action signature will look like this:
[HttpPost]
public ActionResult Edit(AddEditChildProductModel model)
{
...
}
You can fins in Phil Haack's article "Model Binding To A List" useful information about binding collections of Entities to a view.
#for (int i = 0; i < Model.MyCollection.Count; i++)
{
#Html.TextBoxFor(m => m[i].Title)
#Html.TextBoxFor(m => m[i].Author)
#Html.TextBoxFor(m => m[i].DatePublished)
}
public ActionResult UpdateStuff(MyViewModel vm)
{
}
Also you can find solution provided by Steven Sanderson at http://blog.stevensanderson.com/2010/01/28/validating-a-variable-length-list-aspnet-mvc-2-style/. Helped me a lot.