This is an odd problem. I'm making a .Net MVC app that contains a Bitcoin wallet. The problem is that I changed an "IsTestNet" boolean in my "Profile" Model to a 3 choice enum to include "MainNet," "TestNet," and "RegTest" options for the Bitcoin network. I am writing tests for the app so I had to add a "RegTest" network to do testing. The end user using the app should never interact with the RegTest network option so I only need the View to interact with the MainNet and TestNet options for the Bitcoin Network.
The profile creation view looks like this:
This is what the code for the view looks like (Notice I haven't swapped "IsTestNet" for "NetworkMod"):
@model Profile
@{
ViewData["Title"] = "Profiles";
bool isEdit = Model != null && Model.Id != Guid.Empty;
}
<h2>
@(isEdit ? $"Edit profile - {Model.Name}" : "Create profile")
</h2>
<div asp-validation-summary="All" ></div>
<form asp-action="Save">
@if (isEdit)
{
<input type="hidden" asp-for="Id" />
}
<div >
<label asp-for="Name">Profile name</label>
<input asp-for="Name" />
</div>
<div >
<input asp-for="IsTestNet">
<label asp-for="IsTestNet">Is TestNet</label>
</div>
<button type="submit" >Save</button>
</form>
This is the relevant code for the Profile Controller (Notice I haven't swapped "IsTestNet" for "NetworkMod"):
[HttpPost]
public IActionResult Save(Profile profile)
{
if (!ModelState.IsValid)
{
return View(nameof(Create));
}
const string profileExistsError = "A profile with this name already exists. Choose a new name.";
var userId = _manager.GetUserId(User);
Func<bool> containsProfileName = () => _db.Profiles.Any(p => p.UserId == userId && p.Name == profile.Name);
using (var transaction = _db.Database.BeginTransaction())
{
if (profile.Id != Guid.Empty)
{
var prof = _db.Profiles
.FirstOrDefault(p => p.UserId == userId && p.Id == profile.Id);
if (profile is null)
{
return NotFound();
}
// double check that we don't have any profiles with this name first
if (prof.Name != profile.Name && containsProfileName())
{
ModelState.AddModelError("Name", profileExistsError);
return View(nameof(Create), profile);
}
prof.Name = profile.Name;
prof.IsTestNet = profile.IsTestNet;
_db.Profiles.Update(prof);
}
else
{
// double check that we don't have any profiles with this name first
if (containsProfileName())
{
ModelState.AddModelError("Name", profileExistsError);
return View(nameof(Create), profile);
}
var address = new Address
{
ProfileId = profile.Id,
Send = BitcoinHelper.CreatePrivateKey(profile.IsTestNet)
};
var picnicKeys = BitcoinHelper.GeneratePicnicKeys();
profile.UserId = userId;
profile.PublicKey = picnicKeys.PublicKey;
profile.PrivateKey = picnicKeys.PrivateKey;
profile.Addresses = new[] { address };
_db.Profiles.Add(profile);
}
_db.SaveChanges();
transaction.Commit();
}
return RedirectToAction("Index");
}
This is the NEW Profile Model (Notice there is no "IsTestNet" bool because I replaced it with "NetworkMod")
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using amaranth.Models.ViewModels;
using Microsoft.AspNetCore.Identity;
namespace amaranth.Models
{
public class Profile
{
public Guid Id { get; set; }
public string UserId { get; set; }
[Required]
public string Name { get; set; }
public NetworkMod NetworkMod { get; set; }
public string PrivateKey { get; set; }
public string PublicKey { get; set; }
public virtual IdentityUser User { get; set; }
public virtual IEnumerable<Record> Records { get; set; }
public virtual IEnumerable<Address> Addresses { get; set; }
public Address GetCurrentAddress() => Addresses?.FirstOrDefault(a => a.Receive is null);
}
}
And this is the NetworkMod Model as referenced in the Profile Model:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace amaranth.Models.ViewModels
{
public enum NetworkMod {
[Display(Name = "MainNet")]
MainNet,
[Display(Name = "TestNet")]
TestNet,
[Display(Name = "RegTest")]
RegTest
}
}
So ordinarily, I would change the checkbox for "Is TestNet" to a dropdown, but the user should never need to select "RegTest" so it's still just 2 options for the end user which is adequately defined by a checkbox. So how do I modify the view to make it pick between enum options 1 and 2 as a checkbox?
CodePudding user response:
So how do I modify the view to make it pick between enum options 1 and 2 as a checkbox?
One checkbox can only bind one value,so you need to use two checkboxes,here is a demo:
<div >
<input type="checkbox" value="MainNet" name="NetworkMod" />
<label>MainNet</label>
</div>
<div >
<input type="checkbox" value="TestNet" name="NetworkMod" />
<label>TestNet</label>
</div>
js:
@section Scripts{
<script>
$('input[name="NetworkMod"]').on('change', function () {
if ($(this).prop("checked")) {
$('input[name="NetworkMod"]').not(this).prop('checked', false);
}
});
</script>
}