Dictionary inside IDictionary MVC - c#

I had to alter a radio button to include a new value.
To do this I had to put a Dictionary inside an IDictionary. The key pulls in great for the IDictionary but the Dictionary int and string don't pull in at all.
I believe it's my front end code.
Can anyone see what I am doing wrong and provide an example on how to fix?
Action Parameter in Controller
IDictionary<String, Dictionary<int, String>>
View
<fieldset>
<legend class="sr-only">Actions</legend>
<input type="hidden" name="customerId" value="#account.CustomerId" />
<input type="hidden" name="yearSetupId" value="#account.YearId" />
<label class="radio-inline"><input type="radio" name="accountActions[#(account.CustomerId)].Key[#(account.Id)].Value" value="" checked="checked">Do nothing</label>
#{
var possibleActions = account.Balance < 0 ? new[] {
BalanceAdjustmentType.Zeroed, BalanceAdjustmentType.Issued }
: new[] { BalanceAdjustmentType.Under, BalanceAdjustmentType.Sent };
}
#foreach (var action in possibleActions)
{
<label class="radio-inline"><input type="radio" name="accountActions[#(account.CustomerId)].Key[#(account.YearId)].Value" value="#action.BalanceId">#action.Text</label>
}
</fieldset>

I didn't understand your controller parameter means actually.
But I supposed the "accountActions" in your view was the variable of your "controller parameter".
If so, then your could access the nested dict value by accountActions[Key][InnerKey].
<fieldset>
<legend class="sr-only">Actions</legend>
<input type="hidden" name="customerId" value="#account.CustomerId" />
<input type="hidden" name="yearSetupId" value="#account.YearId" />
<label class="radio-inline">
<input type="radio" name="#accountActions[account.CustomerId][account.Id]" value="" checked="checked">
Do nothing
</label>
#{
var possibleActions = account.Balance < 0
? new[] { BalanceAdjustmentType.Zeroed, BalanceAdjustmentType.Issued }
: new[] { BalanceAdjustmentType.Under, BalanceAdjustmentType.Sent };
}
#foreach (var action in possibleActions) {
<label class="radio-inline">
<input type="radio" name="#accountActions[account.CustomerId][account.YearId]" value="#action.BalanceId">
#action.Text
</label>
}
</fieldset>

Related

How to send form values of array/list without correct indexing?

Let's assume that we have model and View like this:
public class Test
{
public List<string> data { get; set; }
}
<form asp-action="View">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input name="data[0]" value="dsa" />
<input name="data[1]" value="asd" />
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
[HttpPost]
public IActionResult View(Test input)
{
return View();
}
I'm sending this form to the controller's method and he sees those elements of data properly.
But if I change indexing to:
<input name="data[0]" value="dsa" />
<input name="data[2]" value="asd" />
then it is not going to work. I know that it makes sense in this way, but is there an option to disable index checking and just insert all those values into list/array with correct indexing?
So, in 2nd case data[0] would be data[0], but data[1] would be data[2].
Just for every "gap" in indexing, move Next objs to fil lthat gap.
You can use just:
<input name="data[]" value="dsa" />
<input name="data[]" value="asd" />
If you specify the index at all, though, it must be in order.

Clearing a collection with c# / asp.net model binding

Is it possible to clear a collection with model bindning?
Sample model class:
public class TestModel
{
public String Name
{
get; set;
}
public List<String> Strings
{
get; set;
}
}
Sample Html:
<form>
<input type="text" name="Name" value="New name" />
<input type="text" name="Strings[]" value="New str1" />
<input type="text" name="Strings[]" value="New str2"/>
<input type="text" name="Strings[]" value="New str3"/>
<input type="submit" />
</form>
And controller code:
public IActionResult Post()
{
var model = new TestModel() { Name = "Old name" };
model.Strings = new List<String>();
model.Strings.Add("Old str 1");
model.Strings.Add("Old str 2");
this.TryUpdateModelAsync(model);
}
In this case the TryUpdateModelAsync will update both Name and Strings but what if I would like to clear the list with TryUpdateModelAsync?
changing html to:
<form>
<input type="text" name="Name" valuye="New name" />
<input type="text" name="Strings" value="" />
<input type="submit" />
</form>
will of course update Strings to a list with one empty / null value and removing input for Strings will keep the old list intact (as expected), but is there any magic trick to just clear that list or set it to null?

Wrong hidden filed value is being passed to the Action Method

Update :
This is an SPA app.So it's having js file also for supporting the submit button.So I think problem is on it.Could you tell me how to modify it to support multiple kind of submit buttons ? At this moment I think it supports only for a single submit button.That is why it always get the first form's hidden field value I think.Thanks.
JS
var $loginForm = $('.login-form');
$loginForm.submit(function (e) {
e.preventDefault();
if (!$('.login-form').valid()) {
return;
}
abp.ui.setBusy(
null,
abp.ajax({
contentType: app.consts.contentTypes.formUrlencoded,
url: $loginForm.attr('action'),
data: $loginForm.serialize()
})
);
});
UI
VM
public class LoginViewModel
{
public string TenancyName { get; set; }
[Required]
public string UsernameOrEmailAddress { get; set; }
[Required]
public string Password { get; set; }
public bool RememberMe { get; set; }
}
CompanyLoginFormViewModel VM :
public class CompanyLoginFormViewModel
{
public LoginViewModel LoginViewModel { get; set; }
public List<TenantListDto> Tenants { get; set; }
}
*.cshtml page
#{
var companyLoginFormViewModel = TempData["CompanyLoginFormViewModel"] as CompanyLoginFormViewModel;
}
#foreach (var tenant in companyLoginFormViewModel.Tenants)
{
<form class="login-form" action="#Url.Action("Login")?returnUrl=#ViewBag.ReturnUrl" name="companyLoginForm" method="post">
<input type="hidden" name="usernameOrEmailAddress" value="#companyLoginFormViewModel.LoginViewModel.UsernameOrEmailAddress" />
<input type="hidden" name="password" value="#companyLoginFormViewModel.LoginViewModel.Password" />
<input type="hidden" name="rememberMe" value="true" />
<input type="hidden" name="companyUrl" value="true" />
<input type="hidden" name="tenancyName" value="#tenant.TenancyName" />
<div class="row margin-top-10">
<div class="col-xs-3">
<button type="submit" class="btn btn-success uppercase">#L("LogIn")</button>
</div>
</div>
</form>
}
Generated html
<form class="login-form" action="/Account/Login?returnUrl=/Application" name="companyLoginForm" method="post" novalidate="novalidate">
<input type="hidden" name="usernameOrEmailAddress" value="fake#gmail.com">
<input type="hidden" name="password" value="fake">
<input type="hidden" name="rememberMe" value="true">
<input type="hidden" name="companyUrl" value="true">
<input type="hidden" name="tenancyName" value="Asset_Management">
<div class="row margin-top-10">
<div class="col-xs-3">
<button type="submit" class="btn btn-success uppercase">Log in</button>
</div>
</div>
</form>
<form class="login-form" action="/Account/Login?returnUrl=/Application" name="companyLoginForm" method="post" novalidate="novalidate">
<input type="hidden" name="usernameOrEmailAddress" value="fake#gmail.com">
<input type="hidden" name="password" value="fake">
<input type="hidden" name="rememberMe" value="true">
<input type="hidden" name="companyUrl" value="true">
<input type="hidden" name="tenancyName" value="Associates">
<div class="row margin-top-10">
<div class="col-xs-3">
<button type="submit" class="btn btn-success uppercase">Log in</button>
</div>
</div>
</form>
<form class="login-form" action="/Account/Login?returnUrl=/Application" name="companyLoginForm" method="post" novalidate="novalidate">
<input type="hidden" name="usernameOrEmailAddress" value="fake#gmail.com">
<input type="hidden" name="password" value="fake">
<input type="hidden" name="rememberMe" value="true">
<input type="hidden" name="companyUrl" value="true">
<input type="hidden" name="tenancyName" value="ALL">
<div class="row margin-top-10">
<div class="col-xs-3">
<button type="submit" class="btn btn-success uppercase">Log in</button>
</div>
</div>
</form>
Post method
[HttpPost]
public virtual async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "", string returnUrlHash = "", bool companyUrl = false)
{
CheckModelState();
// removed for clarity
}
Question : Even though I have press the 2nd submit button,it always send the tenancyName as first submit button's value.That is Asset_Management.Could you tell me why ? Thanks.
Your problem is with the script.
var $loginForm = $('.login-form');
is a collection of all your forms, but
data: $loginForm.serialize(),
will only serialize the first one, so you always posting the vales of the first form. Modify the script to handle the buttons .click() event and get its associated form
$('.btn-success').click(function(e) {
e.preventDefault(); // if you makes the button type="button" this is not required
var form = $(this).closest('.login-form');
if (!form.valid()) {
return;
}
abp.ui.setBusy(
null,
abp.ajax({
contentType: app.consts.contentTypes.formUrlencoded,
url: form.attr('action'),
data: form.serialize()
})
);
});
Why do you even have <form> and <button> at all?
Why not create links in your foreach loop, something like this:
#Html.ActionLink("Login for " + tenant.Name, "LoginAction", new {Id=tenant.Id})
You can style these links all blue and pretty as you like using CSS afterwards.
Update1, you can pass parameters to your controller using the anonymous object. Do you see how I am passing Id? Your Action will need to accept id, see this answer: passing multiple parameters in #html.actionlink()
Update2, passing username and password like this is very bad practice. You are exposing secure credentials to the view. You should forward the user to the login page with username + password input boxes where the user will login.

HTML checbkox values to C# array

I have list of html checboxes in form and I need get checked checboxes values to C# array after form sent, it is possible?
<form id="form1" action="" method="post">
#foreach (var category in ViewBag.Categories)
{
<ul>
<li>
<input type="checkbox" name="Category" value=#category["UUID"] />#category["CategoryName"]<br /> //Generate >20 checkboxes
</li>
</ul>
}
<button type="submit" formmethod="post">Search</button>
</form>
First of all change following line:
<input type="checkbox" name="Category" value=#category["UUID"] />#category["CategoryName"]<br />
to:
<input type="checkbox" name="Category" value="#category["UUID"]"/>#category["CategoryName"]<br />
and now in your action you can get it from Request object or by adding a parameter of name Category to get in the action:
[HttpPost]
public ActionResult SomeAction()
{
var checkedCategories = Request.Form["Category"];
}
or:
[HttpPost]
public ActionResult SomeAction(int[] Category)
{
}
<input type="checkbox" name="Category" value=#category["UUID"] runat="server" />#category["CategoryName"]<br />
include runat="server" in the input type. you can acess in the code behind.

Prevent Multiple Primary When the Checkbox is Checked

I have a Form where I want to limit the Data from my Drop Downlist when the checkbox is checked
So when the Is Primary checkbox is Checked , There will be no 2 Email address that the Is Primary is Both True !! That is what i Want to Prevent
So that When i Save theres a Message window that will Appear and Let the user know that he/she checked the checkbox for the Same Drop Down Value
using (Html.BeginForm("Save", "Worker", FormMethod.Post, new { id = "contactForm" }))
{
<input type="hidden" id="workerId" name="workerId" value="#workerId" />
<p>
<label for="ddlContactType">
Contact Type</label>
<span>
#Html.DropDownList("ddlContactType", new SelectList(ViewBag.ContactTypeList, "ID", "Display_Value", workerContactType), "[Please Select]",
new Dictionary<string, object>
{
{"class","validate[required] inputLong"}
})
</span>
</p>
<p>
<label for="txtContactValue">
Contact Value</label>
<span>
<input type="text" id="txtContactValue" name="txtContactValue" class="validate[required] inputLong" value="" />
<input type="checkbox" name="chkWorkerIsPrimary" id="chkWorkerIsPrimary" value="true"
checked="checked" />
<label>
Is Primary?</label>
</span>
</p>
<p>
<span>
<input type="submit" id="btnAdd" class="styledButton" value="Add" />
</span>
</p>
}
</div>
I need the Validation written in Javascript or Jquery but i dont know how to start :(
Thanks
This is where you begin.
$('#chkWorkerIsPrimary :checkbox').click(function() {
var $this = $(this);
if ($this.is(':checked')) {
// do something
}
else {
//do something else
}
});

Categories