I want to create A form where related data from credit and debit is also added in create action of journal.
I have three tables with code.
public class Journal
{
public int ID { get; set; }
public DateTime journalDT { get; set; }
public decimal Amount { get; set; }
public virtual ICollection<Credit> Credits { get; set; }
public virtual ICollection<Debit> Debits { get; set; }
}
public class Credit
{
public int ID { get; set; }
public int JournalID { get; set; }
public int CodeID { get; set; }
public decimal Amount { get; set; }
public virtual Journal Journal { get; set; }
public virtual Code Code { get; set; }
}
public class Debit
{
public int ID { get; set; }
public int JournalID { get; set; }
public int CodeID { get; set; }
public decimal Amount { get; set; }
public virtual Journal Journal { get; set; }
public virtual Code Code { get; set; }
}
Below is the form code
#using (Html.BeginForm())
{
Inputs for Jurnal Model......
<div class="row">
<div class="col-sm-6 text-center" style="border:1px solid red;">
Credit<br/>
<input type="text" id="Credit[0].CodeID" name="Credit[0].CodeID" value=1 />
<input type="text" id="Credit[0].Amount" name="Credit[0].Amount" value=23.00 />
<input type="text" id="Credit[1].CodeID" name="Credit[1].CodeID" value=2 />
<input type="text" id="Credit[1].Amount" name="Credit[1].Amount" value=123.00 />
<input type="text" id="Credit[2].CodeID" name="Credit[2].CodeID" value=3 />
<input type="text" id="Credit[2].Amount" name="Credit[2].Amount" value=223.00 />
</div>
<div class="col-sm-6 text-center" style="border:1px solid red;">
Debit
<input type="text" id="Debit[0].CodeID" name="Debit[0].CodeID" value=1 />
<input type="text" id="Debit[0].Amount" name="Debit[0].Amount" value=23.00 />
<input type="text" id="Debit[1].CodeID" name="Debit[1].CodeID" value=2 />
<input type="text" id="Debit[1].Amount" name="Debit[1].Amount" value=123.00 />
<input type="text" id="Debit[2].CodeID" name="Debit[2].CodeID" value=3 />
<input type="text" id="Debit[2].Amount" name="Debit[2].Amount" value=223.00 />
</div>
</div>
}
Now the problem is how can i bind the data in create action to Credits and Debits
public ActionResult Create([Journal journal, ICollection<Credit> Credits, Icollection<Debits> Debits)
Related
I have the following 2 model classes:-
public Submission()
{
SubmissionQuestionSubmission = new HashSet<SubmissionQuestionSubmission>();
}
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Npi { get; set; }
public bool Independent { get; set; }
public string Comment { get; set; }
public virtual ICollection<SubmissionQuestionSubmission> SubmissionQuestionSubmission { get; set; }
}
public partial class SubmissionQuestionSubmission
{
public int SubmissionQuestionId { get; set; }
public int SubmissionId { get; set; }
public string Answer { get; set; }
public virtual Submission Submission { get; set; }
}
and i created the following view model:-
public class SubmissionCreate
{
public Submission Submission {set; get;}
public IList<SubmissionQuestion> SubmissionQuestion { set; get; }
public IList<SubmissionQuestionSubmission> SubmissionQuestionSubmission { set; get; }
}
then inside my view i only need to submit back the following fields:-
#model LandingPageFinal3.ViewModels.SubmissionCreate
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Submission.FirstName" class="control-label"></label>
<input asp-for="Submission.FirstName" class="form-control" />
<span asp-validation-for="Submission.FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Submission.LastName" class="control-label"></label>
<input asp-for="Submission.LastName" class="form-control" />
<span asp-validation-for="Submission.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Submission.Npi" class="control-label"></label>
<input asp-for="Submission.Npi" class="form-control" />
<span asp-validation-for="Submission.Npi" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="Submission.Independent" /> #Html.DisplayNameFor(model => model.Submission.Independent)
</label>
</div>
<div class="form-group">
<label asp-for="Submission.Comment" class="control-label"></label>
<textarea asp-for="Submission.Comment" class="form-control"></textarea>
<span asp-validation-for="Submission.Comment" class="text-danger"></span>
</div>
<div id="additionalInfo">
#for (var i = 0; i < Model.SubmissionQuestion.Count(); i++)
{
<label>#Model.SubmissionQuestion[i].Question</label><br />
<input asp-for="#Model.SubmissionQuestion[i].Question" hidden />
<textarea asp-for="#Model.SubmissionQuestionSubmission[i].Answer" class="form-control"></textarea>
<input asp-for="#Model.SubmissionQuestionSubmission[i].SubmissionQuestionId" hidden />
<br />
}
</div>
so i define the following binding inside my post action method, to only bind the fields inside my view, as follow:-
public async Task<IActionResult> Create([Bind(Submission.FirstName,Submission.LastName,Submission.Npi,Submission.Independent" +
"Submission.Comment,SubmissionQuestionSubmission.Answer,SubmissionQuestionSubmission.SubmissionQuestionId")] SubmissionCreate sc )
{
but the sc.Submission and the sc.SubmissionQuestionSubmission will be null inside my action method... so not sure what is the minimum binding i should define, to prevent hacking our application by posting back extra info and navigation properties other than the ones defined in my view?
You don't need to use bind to bind only the fields that appear in your view.
In fact, your view has set the name attribute for the fields you need to display, so
SubmissionCreate sc will only bind the corresponding fields in the view when accepting.
Just use this code to receive:
public async Task<IActionResult> Create(SubmissionCreate sc)
{
return View();
}
Update
Since you only bound some fields in the view, you only need to exclude the SubmissionQuestion field value:
public async Task<IActionResult> Create([Bind("Submission", "SubmissionQuestionSubmission")]SubmissionCreate sc)
{
return View();
}
If you want to be more precise, you can bind the fields you need to the Submission and SubmissionQuestionSubmission classes separately, as follows:
[Bind("FirstName,LastName,Npi,Independent,Comment")]
public class Submission
{
public Submission()
{
SubmissionQuestionSubmission = new HashSet<SubmissionQuestionSubmission>();
}
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Npi { get; set; }
public bool Independent { get; set; }
public string Comment { get; set; }
public virtual ICollection<SubmissionQuestionSubmission> SubmissionQuestionSubmission { get; set; }
}
[Bind("Answer,SubmissionQuestionId")]
public partial class SubmissionQuestionSubmission
{
[Key]
public int SubmissionQuestionId { get; set; }
public int SubmissionId { get; set; }
public string Answer { get; set; }
public virtual Submission Submission { get; set; }
}
I want to save values from a form to my database. I'm using a viewmodel with an selectlist property and a regular model. The value from the dropdown doesn't get saved. Despite being a trivial and seemingly pretty simple thing, I'm pretty lost.
Below my code:
Model:
public class Movie
{
public int MovieID { get; set; }
public string Name { get; set; }
public int StudioID { get; set; }
public Studio Studio { get; set; }
}
My ViewModel:
public class CreateMoviesViewModel
{
public Movie Movie { get; set; }
public IEnumerable<SelectListItem> StudiosSelectList { get; set; }
}
My Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(CreateMoviesViewModel movieViewModel)
{
if (ModelState.IsValid)
{
_context.Add(movieViewModel);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
movieViewModel.StudiosSelectList = new SelectList(_context.Studios.AsNoTracking(), "StudioID", "Name");
return View(movieViewModel);
And finally, my Form:
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Movie.MovieID" />
<div class="form-group">
<label asp-for="Movie.Name" class="control-label"></label>
<input asp-for="Movie.Name" class="form-control" />
<span asp-validation-for="Movie.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Movie.StudioID" class="control-label"></label>
#Html.DropDownListFor(m => m.StudiosSelectList, Model.StudiosSelectList, "Select one")
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
It is probably something wrong with my dropdown list, or with the logic described in the POST section. Any help is greatly appreciated!
You need to pass the selected dropdown value to your model:
public class CreateMoviesViewModel
{
public int SelectedValueId { get; set; } // <-- not sure what are you selecting, this could be MovieId if you are selecting a movie
public Movie Movie { get; set; }
public IEnumerable<SelectListItem> StudiosSelectList { get; set; }
}
Then you can use:
#Html.DropDownListFor(m => m.SelectedValueId, m.StudiosSelectList)
This way, the selected value Id would be passed to your model.
SelectValueId should be initialized to the default value that you want to display in the Dropdown.
I am currently doing asp.net.core with MVC model in my project. I want to create an another form to fetch the data from original form.
In my project, the user will choose an item from a list of products, then it will navigate from a view(product.view) to another view (order.view). While what I want is to pass the values (name, description, colour, price, type) from product view to order view.
This is my Order.model
namespace FurnitureStore.Models
{
public class Order
{
public int OrderID { get; set; }
public string FurnitureName { get; set; }
public string FurnitureDescription { get; set; }
public string FurnitureType { get; set; }
public string FurnitureColour { get; set; }
public decimal FurniturePrice { get; set; }
public string CustomerName { get; set; }
public string CustomerContact { get; set; }
public string CustomerAddress { get; set; }
}
}
This is my original model
namespace FurnitureStore.Models
{
public class Furniture
{
public int ID { get; set; }
public string FurnitureName { get; set; }
public string FurnitureDescription { get; set; }
public string FurnitureType { get; set; }
public string FurnitureColour { get; set; }
public decimal FurniturePrice { get; set; }
}
}
Button-action in first view to Order.View
<a asp-controller="Orders" asp-action="Buy">Buy</a>
Order.View
<div class="form-group">
<label asp-for="FurnitureName" class="control-label"></label>
<input asp-for="FurnitureName" class="form-control" />
<span asp-validation-for="FurnitureName" class="text-danger"></span>
</div>
//Repeated form-group
<input type="submit" value="Create" class="btn btn-default" />
Order.Controller
public ActionResult Buy()
{
return View();
}
[HttpPost]
public ActionResult Buy([Bind("OrderID,FurnitureName,FurnitureDescription,FurnitureType,FurnitureColour,FurniturePrice,CustomerName,CustomerContact,CustomerAddress")] Order order)
{
if (ModelState.IsValid)
{
_context.Add(order);
_context.SaveChanges();
}
return View();
}
For this case you need use tag form in your product view, it look something like this.
[HttpPost]
public ActionResult Buy(Order order)
{
if (ModelState.IsValid)
{
_context.Add(order);
_context.SaveChanges();
}
return View();
}
in your product view
<form method="post" asp-area="" asp-controller="Orders" asp-action="Buy">
<input name="yourFieldName" type="text">
<input name="yourFieldName" type="text">
<input name="yourFieldName" type="text">
<input name="yourFieldName" type="text">
<button type="submit">Submit</button>
</form>
I have been searching all over the internet about MVC many-to-many relationships (and have read every thing about it here too), but I can't seem to solve my problem.
I have a many-to-many relationship between a client and a standard service as seen below.
public class Client
{
public Client()
{
CustomServices = new HashSet<CustomService>();
StandardServices = new HashSet<StandardService>();
}
public int ClientID { get; set; }
public string Name { get; set; }
public Nullable<int> Users { get; set; }
public Nullable<bool> FH { get; set; }
public Nullable<bool> PH { get; set; }
public bool Hosted { get; set; }
public string ShortName { get; set; }
public Nullable<short> AttachmentLimit { get; set; }
public virtual ICollection<CustomService> CustomServices { get; set; }
public virtual ICollection<StandardService> StandardServices { get; set; }
And the standard service.
public class StandardService
{
public StandardService()
{
Clients = new HashSet<Client>();
}
public int StandardServiceID { get; set; }
public string StandardServiceName { get; set; }
public string LogOnAs { get; set; }
public int ServerID { get; set; }
public virtual Server Server { get; set; }
public virtual ICollection<Client> Clients { get; set; }
When creating a new client, I would like to be able to select from a list of check boxes for standard services that the client uses. I am able to get them to show up in the create view using the viewbag, but would like to be able to use a viewmodel.
I would also like to know how to get this to post with default model binding.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ClientID,Name,Users,FH,Hosted,PH,ShortName,AttachmentLimit")] Client client)
{
if (ModelState.IsValid)
{
db.Clients.Add(client);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(client);
}
Here is the create method for the Client Controller.
public ActionResult Create()
{
ViewBag.StandardServices = db.StandardServices.ToList();
return View();
}
Part of my create view is below (that does the check boxes).
<div class="form-group">
#Html.LabelFor(model => model.StandardServices, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#foreach (var StandardService in ViewBag.StandardServices)
{
<div class="checkbox">
<input class="checkbox" type="checkbox" name="StandardServiceID" id="StandardServiceID" value="#StandardService.StandardServiceID"/>
#StandardService.StandardServiceName<br>
</div>
}
</div>
</div>
So how could I go about doing this? I have tried many things, but don't want to go though listing them all. None worked suffice it to say. Any help at all would be appreciated. I don't need the full solution, just some advice on where to go. Thanks!
Based on a comment below; and viewing the link provided, I think I have part of the solution. I just need to work on the post now. Here is what I have for the view model.
public class CreateClientVM
{
public CreateClientVM()
{
ClientStandardServices = new List<StandardService>();
}
public int ClientID { get; set; }
public string Name { get; set; }
public Nullable<int> Users { get; set; }
public Nullable<bool> FH { get; set; }
public Nullable<bool> PH { get; set; }
public bool Hosted { get; set; }
public string ShortName { get; set; }
public Nullable<short> AttachmentLimit { get; set; }
public List<StandardService> ClientStandardServices { get; set; }
public List<StandardServiceVM> StandardServices { get; set; }
}
public class StandardServiceVM
{
public int StandardServiceID { get; set; }
public string StandardServiceName { get; set; }
public bool IsSelected { get; set; }
}
And below is my Client Controller create method.
public ActionResult Create()
{
//ViewBag.StandardServices = db.StandardServices.ToList();
CreateClientVM clientVM = new CreateClientVM();
var ListVM = new List<StandardServiceVM>();
var standardServices = db.StandardServices.ToList();
foreach(var s in standardServices)
{
var viewModel = new StandardServiceVM
{
StandardServiceID = s.StandardServiceID,
StandardServiceName = s.StandardServiceName,
IsSelected = false
};
ListVM.Add(viewModel);
}
clientVM.StandardServices = ListVM;
return View(clientVM);
}
And finally part of my create view.
<div class="form-group">
#Html.HiddenFor(m => m.ClientID)
#Html.LabelFor(m => m.StandardServices, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#for (int i = 0; i < Model.StandardServices.Count; i++)
{
<div class="checkbox">
#Html.HiddenFor(m => m.StandardServices[i].StandardServiceID)
#Html.CheckBoxFor(m => m.StandardServices[i].IsSelected)
#Html.LabelFor(m => m.StandardServices[i].IsSelected, Model.StandardServices[i].StandardServiceName)
</div>
}
</div>
</div>
Here is the html that gets rendered when viewing the page source. I think this looks right, but I'm not entirely sure.
<div class="form-group">
<input data-val="true" data-val-number="The field ClientID must be a number." data-val-required="The ClientID field is required." id="ClientID" name="ClientID" type="hidden" value="0" />
<label class="control-label col-md-2" for="StandardServices">StandardServices</label>
<div class="col-md-10">
<div class="checkbox">
<input data-val="true" data-val-number="The field StandardServiceID must be a number." data-val-required="The StandardServiceID field is required." id="StandardServices_0__StandardServiceID" name="StandardServices[0].StandardServiceID" type="hidden" value="1" />
<input data-val="true" data-val-required="The IsSelected field is required." id="StandardServices_0__IsSelected" name="StandardServices[0].IsSelected" type="checkbox" value="true" />
<input name="StandardServices[0].IsSelected" type="hidden" value="false" />
<label for="StandardServices_0__IsSelected">FHEmailService</label>
</div>
<div class="checkbox">
<input data-val="true" data-val-number="The field StandardServiceID must be a number." data-val-required="The StandardServiceID field is required." id="StandardServices_1__StandardServiceID" name="StandardServices[1].StandardServiceID" type="hidden" value="2" />
<input data-val="true" data-val-required="The IsSelected field is required." id="StandardServices_1__IsSelected" name="StandardServices[1].IsSelected" type="checkbox" value="true" />
<input name="StandardServices[1].IsSelected" type="hidden" value="false" />
<label for="StandardServices_1__IsSelected">FHScheduledReports</label>
</div>
</div>
</div>
Can anyone comment if this looks okay? I believe it does. Now I just need to figure out how to post it.
I have a ViewModel that I am using to POST data back to the server.
[MetadataType(typeof(CompanyAdminViewModel))]
public class CompanyAdminViewModel
{
public Company Company { get; set; }
public RegisterModel User { get; set; }
public CompanyAdminViewModel()
{
}
}
The Company Entity has child entities: Company.CompanyContacts
public class CompanyContact
{
public int CompanyContactId { get; set; }
public int JobTitleId { get; set; }
public int CompanyId { get; set; }
public string Title { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public Nullable<DateTime> BirthDate { get; set; }
public string Gender { get; set; }
[Required]
public string Phone { get; set; }
public string Fax { get; set; }
public string Extension { get; set; }
[Required]
public string Email { get; set; }
public Nullable<DateTime> HireDate { get; set; }
public virtual Company Company { get; set; }
public virtual JobTitle JobTitle { get; set; }
public bool IsActive { get; set; }
}
When I view the pagesource , the data-* attributes are correctly rendered for the model properties.
<div class="editor-label">
<label for="FirstName">FirstName</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-required="The FirstName field is required." id="FirstName" name="FirstName" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="FirstName" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="LastName">LastName</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-required="The LastName field is required." id="LastName" name="LastName" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="LastName" data-valmsg-replace="true"></span>
</div>
When I POST the form, only the password property displays the validation error. When I check the Model.IsValid, all the failed validations are in the collection...
So why, do only some of the validation errors display on the form after an attempted POST?
It would be useful if you added everything about the form ;)
My question though, is does it submit? You have the required filter on a number of fields but with no message (so it probably displays no errors, but does not submit).
Have you tried these:
#Html.ValidationSummary()
And (for the fields you want validated:
#Html.ValidationMessageFor(m => m.FirstName)