I am creating an ASP.Net application that displays records from a SQLite database and incorporating filter options that are built from the records that are coming in since I do not know what kind of data will be in the columns. I have the filter in place and will create the HTML form that will display the field value and how many records with that value there are. However I am not sure how to grab that data since as far as I am aware, the receiving method in the controller will expect a matching parameter for each variable (HTML form: value="bob", the receiving method in the controller takes a parameter such as string bob).
My code for generating the HTML form is:
<div>
<text>Employment:</text> <br />
#foreach (var employment in Model.Employment)
{
<input type="checkbox" value="{#employment.Key}"/>#employment.Key <text>(#employment.Value)</text> <br />
}
<hr />
</div>
Since there could be, for instance, 15 different selection chosen, how would I grab all of the values that are generated? Additionally, there are about 5 more sections like this for filter options. Is it possible to transmit all selections as a dictionary like
<key,<key,value>>
and then parse through the nested dictionaries? The dictionaries would then hold the main category of filters(main key) and then each accepted filter option(parent's value/key) within that category with the a ture(for the parent's value's value).
Edit: Adding some addition code as requested. This is the class that represents an employee for a company:
public class MemberModel
{
public string ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string EmailAddress { get; set; }
public string PhoneNumber { get; set; }
public string Position { get; set; }
public string Department { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string EmploymentStatus { get; set; }
public string Shift { get; set; }
public string Manager { get; set; }
public string Photo { get; set; }
public string FavoriteColor { get; set; }
}
This might not be necessary for the implementation but made sense to me for building this app. This is a class that contains a list of all employees and dictionaries that I use for building the filter options:
public class TeamMembersModel
{
public Dictionary<string, int> Employment { get; set; }
public Dictionary<string, int> Position { get; set; }
public Dictionary<string, int> Shift { get; set; }
public Dictionary<string, int> Department { get; set; }
public Dictionary<string, int> Manager { get; set; }
public List<MemberModel> Employees { get; set; }
}
This code is a condensed version of how I build the form for filtering:
<form asp-action="" asp-controller="TeamMembers" method="get">
<!-- Department -->
<div>
<text>Department:</text> <br />
#foreach (var departments in Model.Department)
{
<input type="checkbox" value="#departments.Key" />#departments.Key <text>(#departments.Value)</text> <br />
}
<hr />
</div>
<!-- This is repeated for each dictionary in the TeamMembersModel class -->
<button type="submit" value="Filter">Filter</button>
</form>
Related
Let's say I have a view-models like this:
public class AbonentViewModel
{
public int? Id { get; set; }
public string ClientName { get; set; }
public List<AbonentCertificate> Certificates { get; set; }
}
public class AbonentCertificate
{
public string Name { get; set; }
public string FileName { get; set; }
}
I want to write a tag helper which could show list of Certificates using custom html like this:
<multi-list asp-for="Certificates">
<div class="list-item">
<input asp-for="Name" />
<input asp-for="FileName" />
</div>
</multi-list>
Html inside th multi-list element would be repeated for each certificate object with appropriate values set.
Is there any way to do this?
I'm trying to post a form containing a dictionary of complex types.
The dictionary looks like this:
public Dictionary<Question, List<QuestionAlternative>> Questions { get; set; }
One question can have many alternatives.
The question itself looks like this:
public class Question
{
public Guid Id { get; set; }
public string Text { get; set; }
public Guid TestId { get; set; }
public Test Test { get; set; }
public ICollection<QuestionAlternative> QuestionAlternatives { get; set; }
public Guid? QuestionTypeId { get; set; }
public QuestionType QuestionType { get; set; }
}
And then there's the QuestionAlternative:
public class QuestionAlternative
{
public Guid Id { get; set; }
public string Alternative { get; set; }
public Guid QuestionId { get; set; }
public Question Question { get; set; }
}
My form looks like this:
<form asp-controller="Answer" asp-action="AnswerMe" method="post">
#foreach (var questionPair in Model.Questions)
{
#Html.Hidden("Questions[" + questionIndex + "].Key.Id", questionPair.Key.Id)
<br />
foreach (var alternative in questionPair.Value)
{
<label for="#alternative.Id">#questionPair.Key.Text</label>
<textarea id="#alternative.Id" name="#("Questions["+ questionIndex + "].Value["+ index +"]")"></textarea>
index++;
}
}
questionIndex++;
}
<input type="submit" class="button" value="Answer" />
</form>
The ActionResult that i'm posting to looks like this:
[AllowAnonymous]
[HttpPost("AnswerMe")]
public IActionResult AnswerMe([FromBody]AnswerViewModel model)
{
foreach(var item in model.Questions) //throws exception
....
}
and my viewmodel:
public class AnswerViewModel
{
public ODELDAL.Entities.Test Test { get; set; }
public Dictionary<Question, List<QuestionAlternative>> Questions { get; set; }
public Guid SelectedRole { get; set; }
}
When I post my form the dictionary named Questions is null.
Is it possible to achieve this with the default modelbinder or do i need to build a custom one.
If so, how would that solution look like?
Thanks in advance
Since a Question already possesses a collection of QuestionAlternative why not use a simple collect (List, array....etc) in your view model...
public class AnswerViewModel {
public ODELDAL.Entities.Test Test { get; set; }
public Question[] Questions { get; set; }
public Guid SelectedRole { get; set; }
}
...and an updated view...
<form asp-controller="Answer" asp-action="AnswerMe" method="post">
#for(int i = 0; i < Model.Questions.Length; i++) {
#Html.HiddenFor(m => m.Questions[i].Id)
<br />
for(int j = 0; j < m.Questions[i].QuestionAlternatives.Count; j++) {
#Html.LabelFor(m => m.Questions[i].QuestionAlternatives[j].Alternative,m.Questions[i].QuestionAlternatives[j].Text)
#Html.TextAreaFor(m => m.Questions[i].QuestionAlternatives[j].Alternative)
}
}
<input type="submit" class="button" value="Answer" />
</form>
The model binder will have an easier task of reconstructing your model using this approach as it will be able to use the expressions to generate the ids for the html tags.
For example, the hidden input will look something like this when generated
<input data-val="true" id="Questions_0__Id" name="Questions[0].Id" value="{Some-Guid-Value_Here}" type="hidden">
I have to create a notes app for homework and it should contain Notes with a List of Tags as property. My generated Notes object looks like this:
public partial class Note
{
public Note()
{
this.Tags = new HashSet<Tag>();
}
public int Id { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public string Author { get; set; }
public string Mail { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
Also I have a generated Tag Object:
public partial class Tag
{
public Tag()
{
this.Notes = new HashSet<Note>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
This is done with a many to many relationship, i have no entity for NoteTags but a database table.
Now how do I make it possible for the user to edit the tags for a note?
I tried many things already, for example this but that did not work for me because i would have to edit the generated model.
Idk if this helps to understand my situation, here's my editortemplate tag.cshtml:
#model IEnumerable<CRUDApp.Models.Tag>
#foreach (var item in Model)
{
#Html.EditorFor(modelItem => item.Name)<br />
}
Whenever I post the form in the edit mode, Tags will be null within the Note object.
UPDATE: fixed this issue by adding the name attribute to the select tag that was added in order for it to be added to the formelement upon submit.
I have a partial view that get's passes a model that has a foreign key. The partial view's sole purpose is to create a new object in the database for this model. I created a drop down for one of the fields based on something outside of the model and now when I post the form, that field isn't included in the api post to create the record.
(for those familiar, yes, this is pretty much the contact example out of the box, I'm trying to extend it a bit and could use some help)
<form id="addContact" data-bind="submit: createContactFromForm">
#Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
#Html.EditorForModel()
<div class="editor-label"><label>Store:</label></div>
<div class="editor-field" id="storediv">
<select id="StoreId" **name="StoreId"** data-bind="options: stores, optionsText: 'Name', optionsValue: 'Id', optionsCaption: 'Choose...'"></select>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
How can I get the Store field to be part of the model on form submit? I'm overriding the submit to call the createContactFromForm function in the knockoutjs viewmodel.
Updated with portion of the viewmodel that is being called:
self.createContactFromForm = function (formElement) {
// If valid, post the serialized form data to the web api
$(formElement).validate();
if ($(formElement).valid()) {
$.post("api/contacts", $(formElement).serialize(), "json")
.done(function (newContact) {
self.contacts.push(newContact);
$('#addContact')[0].reset();
});
}
}
Server side model:
public Contact()
{
this.Created = DateTime.Now;
this.Emails = new List<Emails>();
}
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required, MaxLength(256)]
public string FirstName { get; set; }
[Required, MaxLength(256)]
public string LastName { get; set; }
[ScaffoldColumn(false)]
public string Name { get { return string.Concat(this.FirstName, " ", this.LastName); } set { } }
[MaxLength(256)]
public string EmailAddress {
get
{
return this.Emails.Count == 0 ? string.Empty : this.Emails[0].EmailAddress;
}
set
{
if (this.Emails.Count == 0)
{
this.Emails.Add(new Emails());
}
this.Emails[0].EmailAddress = value;
}
}
[MaxLength(50)]
public string PhoneNumber { get; set; }
[MaxLength(256)]
public string Address { get; set; }
[MaxLength(256)]
public string City { get; set; }
[MaxLength(50)]
public string State { get; set; }
[MaxLength(256)]
public string ZipCode { get; set; }
[Required]
[ScaffoldColumn(false)]
public int StoreId { get; set; }
public Store Store { get; set; }
[ScaffoldColumn(false)]
public DateTime Created { get; set; }
public virtual IList<Emails> Emails { get; protected set; }
I am learning, and managed to make a nice info display page, displaying lists of transactions. However, I have no added DropDown box, which has a list of Bank Accounts. It's defaulted to All.
When the user selects an account, and presses the submit button, the page should then reloca with only transactions for that account.
I have created the drop down, and the form for it, like this:
<form id="form1" runat="server">
<h2>
Transactions:</h2>
<p>
<%
using (Html.BeginForm())
{
%>
Bank Account:
<% =Html.DropDownList("ddAccounts", Model.BankAccountItems)%> <input id="Submit1" type="submit" value="Select" />
<%
}
%>
</p>
</form>
My model contains this:
public class AccountTransactionDisplay
{
public AccountTransactionDisplay()
{
DisplayLines = new List<AccountTransactionDisplayLine>();
}
public SelectList BankAccountItems { get; set; }
public List<AccountTransactionDisplayLine> DisplayLines {get; set; }
public string ClosingBalance { get; set; }
}
public class BankAccountDropdownItem
{
public string Text {get; set;}
public string Value {get; set;}
}
public class AccountTransactionDisplayLine
{
public string RowColouring { get; set; }
public string TransactionDate { get; set;}
public string PayeeName { get; set; }
public string Amount { get; set; }
public bool AmountIsDebit { get; set; }
public string CategoryName { get; set; }
public string CostCenterName { get; set; }
public string BudgetName { get; set; }
public string RunningTotal { get; set; }
public bool RunningTotalIsDebit { get; set; }
public bool AlternateRowColour { get; set; }
public bool HasSplitItems { get; set; }
}
So, AccountTransactionDisplay is the model I pass to the view. In that model, I have this:
public SelectList BankAccountItems { get; set; }
That holds a list of items that are displayed in my Drop Down. That is being displayed correctly.
However, when the user clicks the submit button, I am unsure how to get the selected value back.
I thought that I would have a method in my controller that accepts the POST... So, I have added this:
[HttpPost]
public ActionResult Transactions(AccountTransactionDisplay model)
{
AccountTransactionDisplay trans = GetTransactions();
return View(trans);
}
And if I set a breakpoint, it is hitting this, but it seems model is empty. I need to add the id of the selected account ot the GetTransactions method, to do the filtering.
When your page renders, view the source. Whatever the name attribute of the select element is, that is the name of a property you will need to add to your model, then the model binder will bind that value to your model. When a form is submitted, only name/value pair of the form fields are submitted (for the most part), so the select element's name will be in the form data as well as its selected value, all of the options are not posted back, so MVC has no way of rebinding your SelectList property.
HTH