Suppose I have the following model
public class MyModel {
public ProgramModel(Guid id, string name, string description, Currency currency) {
Id = id;
Name = name;
Description = description;
Currency = currency;
}
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Currency Currency { get; set; }
}
The type Currency is
public class Currency {
public Currency(string numericCode, string code, string name) {
NumericCode = numericCode;
Code = code;
Name = name;
}
public string NumericCode { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
Usage example
var currency = new Currency("978", "EUR", "Euro");
Within my Razor page model class I have
[BindProperty]
public MyModel MyModel { get; set; }
[BindProperty]
public IEnumerable<Currency> AllCurrencies { get; set; }
Thanks to this i can render a select item in the view with code similar to this one
<select class="form-select" asp-for="MyModel.Currency">
@foreach (var currency in Model.AllCurrencies) {
if (currency.Code == Model.MyModel.Currency.Code) {
<option value="??????" data-numericcode="@currency.NumericCode"
data-code="@currency.Code" data-name="@currency.Name" selected="">
@currency.Name</option>
}
else {
<option value="??????" data-numericcode="@currency.NumericCode"
data-code="@currency.Code" data-name="@currency.Name">
@currency.Name</option>
}
}
</select>
Is there any way to instruct the model binder to recreate the Currency
object when a different option item is selected on the client?
Is there any way to instruct the model binder to recreate the Currency object when a different option item is selected on the client?
You can add hidden fields in the form to pass the properties of Currency like:
<select id="currencySelect" class="form-select" asp-for="MyModel.Currency" onchange="updateCurrencyFields()">
@foreach (var currency in Model.AllCurrencies)
{
if (currency.Code == Model.MyModel.Currency.Code)
{
<option value="??????" data-numericcode="@currency.NumericCode"
data-code="@currency.Code" data-name="@currency.Name" selected="">
@currency.Name
</option>
}
else
{
<option value="??????" data-numericcode="@currency.NumericCode"
data-code="@currency.Code" data-name="@currency.Name">
@currency.Name
</option>
}
}
</select>
<input type="hidden" asp-for="MyModel.Currency.NumericCode" id="NumericCode" />
<input type="hidden" asp-for="MyModel.Currency.Code" id="Code"/>
<input type="hidden" asp-for="MyModel.Currency.Name" id="Name"/>
</div>
<button type="submit">Submit</button>
</form>
<script>
function updateCurrencyFields() {
var select = document.getElementById("currencySelect");
var numericcode = select.options[select.selectedIndex].getAttribute("data-numericcode");
var code = select.options[select.selectedIndex].getAttribute("data-code");
var name = select.options[select.selectedIndex].getAttribute("data-name");
document.getElementById("NumericCode").value = numericcode;
document.getElementById("Code").value = code;
document.getElementById("Name").value = name;
}
</script>
And code in the MyCurrencyPageModel like:
public class MyCurrencyPageModel : PageModel
{
private readonly ApplicationDbContext _context;
public MyCurrencyPageModel(ApplicationDbContext context)
{
_context = context;
}
[BindProperty]
public MyModel MyModel { get; set; }
public IEnumerable<Currency> AllCurrencies { get; set; }
public void OnGet()
{
AllCurrencies = _context.Currencies.ToList();
MyModel = new MyModel(Guid.NewGuid(), "Example Program", "Description", AllCurrencies.First());
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page();
}
MyModel.Id = Guid.NewGuid();
var item = _context.Currencies.Where(v=>v.Code ==MyModel.Currency.Code).FirstOrDefault();
MyModel.Currency = item;
_context.MyModels.Add(MyModel);
_context.SaveChanges();
return RedirectToPage("Index");
}
}
With the test result: