I am coverting my app from webforms to mvc, at the moment i am at a design issue (well i just dont know how to do it in mvc).
Basically my model would be something like this:
public class DamagedItem
{
public Int32 LoanId {get;set;}
public String IdentityCode {get;set;}
public virtual ICollection<DamagedItems> DamagedItems {get;set;}
}
In my controller i would like to do:
public ActionResult Add(DamagedItem damagedItem)
{
//Do update logic here
}
Then in my view i can add to the ICollection as needed.
But, i can't do this because if i try and access the ICollection from my controller it is null.
Here is an image of when i want to do:
I just dont know how to lay it out in my view, how to i add such items to my ICollection, update the view then when i need to save i have access to what i have added from my controller?
Thanks,
Nick
Edit:
I was thinking of using a partial in the view and doing all the logic for the bottom half using ajax and storing it in a session variable, but i would prefer NOT to make it reliant on ajax.
It is better to separate: you shoud have 2 actions, which produce 2 view.
You should have LoadInformationModel classe:
public class LoadInformationModel
{
public string StudentCode { get; set; }
public string FirstName { get; set; }
// etc..
public ICollection<Damage> Type { get; set; }
}
corresponding action
[HttpGet]
public ActionResult LoanInformation(int id)
{
var loanInfo = // get data by given id..
var model = new LoadInformationModel {
StudentCode = loanInfo.StudentCode,
// etc
Type = new List<Damage> { new Damage { Value = "Damaged"}, new Damage { Value = "Damaged Again" }
}
return View(model);
}
As well as RepairDataModel class
public class RepairDataModel
{
public bool CoveredByWarranty { get; set; }
public ICollection Status { get; set; }
}
And corresponding action
[HttpGet]
public ActionResult Repair(int id)
{
// logic
return View(model);
}
Your task is to create Post handler, that would save data to DB then form submitted
[HttpPost]
public ActionResult(RepairDataModel model)
{
// save to db
return View();
}
The view returned by Index() method, could be created like
#Html.RenderAction("LoanInformation")
#Html.RenderAction("Repair")
The rest depends on your desing and imagination. I hope that would give you direction.
What I can see is only the DamagedItem lacks a contructor with values for Collection;
public class DamagedItem
{
public DamagedItem()
{
DamagedItems = new List<DamagedItems>();
DamagedItems.Add(new DamagedItem { Description = "Damaged" } );
}
public Int32 LoanId {get;set;}
public String IdentityCode {get;set;}
public virtual ICollection<DamagedItems> DamagedItems {get;set;}
}
Related
I'm trying to add an object using a PartialView inside a popup. It's a simple Rental application for which the data model was generated Model First through Entity Framework. The Controllers and Views have mostly been Scaffolded by EF. The relationship between RentalApplication and RentalObject is 1 to many, meaning a RentalObject always has to have 1 RentalApplication.
My controller looks like this:
// GET: /Calendar/Add/1
// Create a PartialView using a RentalObject as the model.
// Use the provided ID to lock in the RentalApplication.
[HttpGet]
public PartialViewResult Add(int id)
{
return PartialView(
new RentalObject(db.RentalApplicationSet.FirstOrDefault(x => x.Id == id)));
}
// POST: /Calendar/Add
// Save the submitted RentalObject to the db
[HttpPost]
public ActionResult Add(RentalObject rentalobject)
{
if (ModelState.IsValid)
{
try
{
db.RentalObjectSet.Add(rentalobject);
db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
return View();
}
My object looks like this:
public partial class RentalObject
{
public RentalObject()
{
this.Lease = new HashSet<Lease>();
}
public RentalObject(RentalApplication rentapp)
{
this.Lease = new HashSet<Lease>();
RentalApplication = rentapp;
PricePerHour = RentalApplication.DefaultPricePerHour;
Currency = RentalApplication.DefaultCurrency;
}
public int Id { get; set; }
public string Name { get; set; }
public bool IsAvailable { get; set; }
public string Illustration { get; set; }
public string Description { get; set; }
public decimal PricePerHour { get; set; }
public string Currency { get; set; }
public virtual ICollection<Lease> Lease { get; set; }
public virtual RentalApplication RentalApplication { get; set; }
}
So when I'm opening the popup (using #Ajax.ActionLink to GET the first controller Add action) I'm creating a RentalObject WITH a RentalApplication (2nd constructor) to use as the model. This works so far, the popup dialog shows the values PricePerHour and Currency from the RentalApplication.
However, when I submit the form in my PartialView popup everything gets copied over BUT the RentalApplication object. It somehow ends up creating a new RentalObject object using the PricePerHour and Currency from the original RentalApplication, but doesn't include the object itself under the RentalApplication property. My debugger even goes to the first constructor for RentalObject.
So I guess it's having trouble keeping a complex object inside another object when submitted from controller to view (GET) and back to controller (POST). Is this just poor practice on my part? Should I be using a ViewModel?
In the past I've had to use #Html.HiddenFor(m=>m.yourObjectHere) on objects that were not changed in the form to keep them from getting new-ed up again. I did this for every object I didn't use in the form (about 2 or 3).
Hope this helps.
I'm trying to add a new item to an existent list in my MVC application, my problem that's I don't know the correct approach to do it.
I've done this so far:
My Customer code:
Controller
public class CustomerController : Controller
{
public CustomerBusiness customerBusiness { get; set; }
public CustomerController()
{
customerBusiness = new CustomerBusiness();
}
//Some code that makes CRUD and more these methods
[HttpGet]
public ActionResult ViewAllJobOfferts(int id)
{
var cust = customerBusiness.GetById(id);
return View(cust.JobOfferts);
}
public ActionResult CreateJobOffert(int id)
{
var cust = customerBusiness.GetById(id);
return View(cust);
}
/* [HttpPost]
public ActionResult CreateJobOffert(JobOffertModel jobOffert)
{
return View();
}*/
}
I have a relationship 1 to n between my entities Customer and JobOffert, and the method ViewAllJobOfferts works fine, but I got stuck when I try to add a new JobOffert.
I have a couple of questions, here we go:
I must to create a controller special to JobOfferts, or control
inside the CustomerController?
When I try to create the view that will submit the form to new
JobOffert I didn't know how to link the customer to this new
JobOffert, f I try create a page using customer model, I do not have the JobOffert attributes and if I create using the JobOffert model, I dont know how make the link between these two objects. how must I do this?
PS.: Here the code of both models:
JobOffert Model
Customer Model
I must to create a controller special to JobOfferts, or control inside
the CustomerController?
Not necessarily, controller like other class should follow SRP (Single Responsibility Principle). In this case as long as CustomerController facilitating information related to Customer, it's completely fine.
When I try to create the view that will submit the form to new JobOffert I didn't know how to link the customer to this new JobOffert, f I try create a page using customer model, I do not have the JobOffert attributes and if I create using the JobOffert model, I dont know how make the link between these two objects. how must I do this?
The link between the customer and JobOffer is as you defined One-to-Many and entities contains references to each other. E.g. You can find all JobOffer for a customer whose Id is 1024 by querying JobOffer table where customerID = 1024. Likewise each JobOffer is traceable by Customer reference in entity class.
Now about creating a new JobOffer for a customer this is how you can go about:
public class CustomerController : Controller
{
public CustomerBusiness customerBusiness { get; set; }
public CustomerController()
{
customerBusiness = new CustomerBusiness();
}
//Some code that makes CRUD and more these methods
[HttpGet]
public ActionResult ViewAllJobOffersForCustomer(int customerId)
{
ICollection<JobOfferModel> model = customerBusiness.GetAllJobOffersByCustomerId(customerId);
return View(model);
}
[HttpGet]
public ActionResult CreateJobOffer()
{
// Blank model object to accept values from user,
// you may like to create a view model based on UI needs.
JobOfferModel jobOfferModel = new JobOfferModel();
return View(jobOfferModel);
}
[HttpPost]
public ActionResult CreateJobOffer(JobOfferModel jobOffer)
{
// You get a filled object here that contains customer id and job offer details
customerBusiness.CreateJobOffer(jobOffer);
return RedirectToAction("ViewAllJobOffersForCustomer", new { customerId = jobOffer.CustomerId });
}
Sample business service class:
public class CustomerBusiness
{
public ICollection<JobOfferModel> GetAllJobOffersByCustomerId(int customerId)
{
// TODO: Fetch job offer details from persistent store
// E.g.
// dataContext.JobOffers.Where(x => x.CustomerId == customerId).ToList();
throw new NotImplementedException();
}
public void CreateJobOffer(JobOfferModel jobOffer)
{
// TODO: Add job offer details in persistent store
// E.g.
// dataContext.JobOffers.Add(jobOffer);
}
}
Modified entity classes:
public class JobOfferModel
{
[Key]
public int Id { get; set; }
public string Description { get; set; }
[Required]
[DefaultValue(false)]
public bool Acepted { get; set; }
[Required]
[DefaultValue(true)]
public bool Active { get; set; }
[Required]
[Column(TypeName = "DateTime2")]
public DateTime JobDate { get; set; }
[ForeignKey("Id")]
public int CustomerId { get; set; }
public virtual CustomerModel Customer { get; set; }
}
public class CustomerModel
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Column(TypeName = "DateTime2")]
public DateTime BirthDate { get; set; }
public int PhoneNumber { get; set; }
public ICollection<JobOfferModel> JobOffert { get; set; }
}
So basically you will have a method in CustomerController that returns empty ViewModel or Model object. On view you will make customerId hidden. So that when form is posted it is mapped to correct customer along with JobOffer details. Once you have model object in HttpPost method you just need to insert an entry in JobOffer table (any persistent store) with customerId associated with it.
There are other nitty gritty but above typical approach will give you a good start I hope. Cheers
So I just created a method that inherits with Facebook and retrieves some information from a user.
What I want now is to send that information to another method so I can put that information to my database.
I'm going to show you the last "stick" in my first method (where I retrieve facebook info) and show you the first "stick" of the second method. Please if you have any ideas on how to do this, reply!
So this is when I add all facebook info from my AuthorizeFacebook method.
GetFacebook.Add(new FacebookInformation
{
Birthday = fbBirthday,
FbEmail = fbEmail,
FbId = fbId,
FbImage = fbPicture,
FbLastName = fbLastName,
Location = fbLocation,
FbName = fbName,
});
model.FacebookInformation = GetFacebook;
and after this I got a new method only:
public void CreateUser()
{
// get the "GetFacebook" class in here?
}
your question is very unclear. Are you looking for something like this:
public void CreateUser(IEnumerable<FacebookInformation> facebookInfo)
{
// write everything from facebookInfo into database
}
You can do something like this:
return RedirectToAction("CreateUser", "SomeController", model);
where model is this model.FacebookInformation = GetFacebook; where you put the information. You can even use your current model's property to pass on:
model.FacebookInformation = GetFacebook;
return RedirectToAction("CreateUser", "SomeController", model.FacebookInformation);
and use
public void CreateUser(List<FacebookInformation> info)
{
// get the "GetFacebook" class in here?
}
if you don't need the whole model you can create smaller model only for that property "FacebookInformation" and pass only this model like this:
publuc class FacebookInformationModel
{
public sometype Birthday { get; set; }
public sometype FbEmail { get; set; }
public sometype FbId { get; set; }
public sometype FbImage { get; set; }
public sometype FbLastName { get; set; }
public sometype Location { get; set; }
public sometype FbName { get; set; }
}
or if GetFacebook returns collection
public class FacebookInformationModel
{
public List<FacebookInformation> info { get; set; }
}
and then pass it at the end of the 1st method like this again :
FacebookInformationModel info = GetFacebook;
return RedirectToAction("CreateUser", "SomeController", info);
the get method looks like this:
public void CreateUser(FacebookInformationModel model)
{
// get the "GetFacebook" class in here?
}
I'm just guessing here as you have not provided what GetFacebook is as structure( I guess some sort of collection as you use .Add) and also what model.FacebookInformation property holds as values , but i assume it is something like List.
It's difficult for me for developping an functionality without JavaScript..
I have a ViewModel :
public class AccountRegisterViewModel
{
#region Properties
public User User { get; set; }
public ExternalAccounts ExtAccounts { get; set; }
public LocalPassword Password { get; set; }
public Company CompanyARegister { get; set; }
public Company CompanyBRegister { get; set; }
public bool SameCompanies { get; set; }
public int NbCompanies { get; set; }
...
}
In view, i have a link with checkbox for copying the first company with the second
But I don't know how pass this viewModel (View to Controller) for keeping my data and return the same View with the copie of company..
i try this, in view :
#Html.ActionLink("Click", "CopyCompanies","Account", new { model = Model })
#Html.CheckBoxFor(model => model.SameCompanies)
In Controller :
[AllowAnonymous]
public ActionResult CopyCompanies(AccountRegisterViewModel model)
{
...
if (model.SameCompanies)
{
// copie
}else //clear
...
return View("Step2Register", model);
}
Any idea ?? Thank you for your help
If the CopyCompanies action method requires the AccountRegisterViewModel object, then you will need to provide it. Unfortunately, you will not be able to provide the value using the approach you are following when creating the link.
Your two options would be to have a hidden field for each property in AccountRegisterViewModel and then let the model binding create the object, but even this would not be ideal, since the viewModel is composed of complex objects, so you would have way too many hidden fields.
Your second option, which I think is a better approach, would be to pass in some kind of Id that corresponds to the AccountRegisterViewModel that CopyCompany can use to look up the values it would need.
I have the beginnings of an ASP.NET MVC3 application that is supposed to implement scheduling. I have the following in my model:
public class Schedule
{
public int ScheduleID { get; set; }
public bool isDisabled { get; set; }
[DisplayName("For Delivery")]
public bool isDeliver { get; set; }
public int Count { get; set; }
public virtual ICollection<TimeofDay> Times { get; set; }
public virtual Location Location { get; set; }
public int Week { get; set; }
public int weekday { get; set; }
}
public class TimeofDay
{
[Key]
public int TimeID {get;set;}
public DateTime Time { get; set; }
}
The model is supposed to accept 0 or more Time of Day entities that I pass by using JavaScript to create a new input field:
function createtimefield() {
var TimeDiv = document.getElementById('timefields');
var newDivInput = document.createElement("input");
newDivInput.name = "Times";
idText="Time" + GLOBAL_timeDivIdCount++;
newDivInput.id = idText;
newDivInput.value = "12:00 am";
TimeDiv.appendChild(newDivInput);
}
My Controller will work file for accepting the data passed up until I add data to the time fields. This is supposed to create new entities in the TimeofDay table that gets generated by the model, and link back to the the ScheduleID. I don't want two interfaces to input this simple data, but can't seem to find the way to create both entities with MVC3 in a single action. Anyone have any ideas?
Andrew
(Thank you for reading)
As requested the controller was:
public ActionResult Create(Schedule schedule, string[] schedTimes)
{
if (ModelState.IsValid)
{
Schedule newschedule = db.Schedule.Add(schedule);
db.SaveChanges();
return RedirectToAction("Index");
}
......
}
I now realize I need to create a view model that will encompass both my schedule class and an array of strings. I will create the schedule and then iterate through the array of strings and create TimeofDay objects
for inputs to bind with times collection ur form fields need to have indexed names like
Times[0].TimeID // this would probably be hidden field
Times[0].Time
Times[1].TimeID
Times[1].Time
.
.
Times[n].TimeID
Times[n].Time
when you do this there might be other issues when deleting rows from the middle. there are lot of blog posts on this out there. Phil haack's post is my favorite as it explains in very simple way how can you have non sequential indices for list binding. For more links please look at my answer to this question
I attempted to create a view model to support this by extending my model as follows:
public class ScheduleCreate
{
public Schedule schedule {get;set;}
public string[] schedTimes {get;set}
}
I then modified my view by changing:
#model scheduler.Models.Schedule
to:
#model scheduler.Models.ScheduleCreate
I additionally changed all of the model.(parameter) to model.schedule.(parameter)
Then I changed my controller to:
public ActionResult Create(ScheduleCreate mod)
{
if (ModelState.IsValid)
{
Schedule newschedule = db.Schedule.Add(mod.schedule);
if (mod.schedTime != null)
{
foreach (string instanceTime in mod.schedTimes)
{
newschedule.Times.Add(new {Time = DateTime.Parse(instanceTime) }); // unteseted
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
PopulateDropDown();
return View(mod.schedule);
}