Bind Gender with Radio button in Create and Edit in MVC - entity-framework

I want to show Gender Male Radio Button and Female Radio button on create and on Edit the selected radio button if male then male should be selected if Female then female should be checked.
Model
[Table("tblUserData")]
public class test
{
[Key]
public int Id { get; set; }
public string FullName { get; set; }
public Nullable<bool> Gender { get; set; }
}
Create View
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>test</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.FullName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FullName)
#Html.ValidationMessageFor(model => model.FullName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Gender, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Gender)
#Html.ValidationMessageFor(model => model.Gender)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
How do I replace the
#Html.EditorFor(model => model.Gender)
With
#Html.RadioButtonFor(model=>model.Gender)
It asks for one more parameter where do I get it from as its a Bit in sql if its 0 then Gender is Male if 1 then Female.
Same I want to do it for edit so that user can see the Gender and update it through radio buttons.

Assuming your razor view is strongly typed to your class,test
#model test
#using (Html.BeginForm())
{
#Html.RadioButtonFor(model => model.Gender, true)
<span>Male</span>
#Html.RadioButtonFor(model => model.Gender, false)
<span>FeMale</span>
<input type="submit" />
}
For your edit view, the same code will work as long as you are sending a valid object of test to your view. Based on the value on the Gender property, it will select the corresponding radio button.
public ActionResult Edit(int id)
{
var vm = yourSbContext.tests.FirstOrDefault(s=>s.Id==id);
if(vm!=null)
{
return View(vm);
}
// to do : Return a Not found/404 response/view
}

Related

How can I bind form fields to a nested model on post?

I am coding a solution where the user will submit a form, posting the values back to my ASP.NET MVC controller. My model is complex and the form fields are contained in a nested object (I'm using CQRS via MediatR). When I submit the form, the values come across as null. How can I get the complex model to recognize the form fields?
Here is my code:
Controller:
[HttpPost]
[Route("edit")]
public async Task<IActionResult> Edit(UpdateApplicationCommand command)
{
await _mediator.Send(command)
.ConfigureAwait(false);
return RedirectToAction("Index");
}
Models:
public class UpdateApplicationCommand : IRequest<Unit>
{
public ApplicationEditGeneralViewModel ApplicationEditGeneralViewModel { get; set; } = null!;
}
public class ApplicationEditGeneralViewModel
{
[Required]
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
}
View:
#model ApplicationEditGeneralViewModel
<form method="post" asp-action="Edit" asp-controller="Applications">
<div class="form-floating mb-3">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control", placeholder = "Application Name"})
<label for="Name">Application Name</label>
</div>
<div class="form-floating mb-3">
#Html.TextBoxFor(m => m.Description, new { #class = "form-control", placeholder = "Application Description"})
<label for="Description">Application Description</label>
</div>
<div class="d-flex flex-row-reverse bd-highlight">
<input type="submit" value="Submit" class="btn btn-primary mt-2" />
</div>
</form>
I've tried to reduce the complex model to its fields, by placing the contents of the ApplicationEditGeneralViewModel directly into the UpdateApplicationCommand class. This worked, but I'd really like to keep the nested structure so that I can reuse the ApplicationEditGeneralViewModel object.
I saw this solution here:
How to bind nested model in partial view
But I'd rather avoid adding the name as a route object (if possible) for every form field. Is there another, more simple way that I can do this?
The first way, you can custom model binding like below:
public class CustomModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
var model = new UpdateApplicationCommand()
{
ApplicationEditGeneralViewModel = new ApplicationEditGeneralViewModel()
{
Description = bindingContext.ValueProvider.GetValue("Description").ToString(),
Name = bindingContext.ValueProvider.GetValue("Name").ToString()
}
};
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
Apply the custom model binding like below:
[HttpPost]
public async Task<IActionResult> Edit([ModelBinder(typeof(CustomModelBinder))]UpdateApplicationCommand model)
{
//.....
}
The second way, just change your razor view like below:
#model UpdateApplicationCommand
<form method="post">
<div class="form-floating mb-3">
#Html.TextBoxFor(m => m.ApplicationEditGeneralViewModel.Name, new { #class = "form-control", placeholder = "Application Name"})
<label for="Name">Application Name</label>
</div>
<div class="form-floating mb-3">
#Html.TextBoxFor(m => m.ApplicationEditGeneralViewModel.Description, new { #class = "form-control", placeholder = "Application Description"})
<label for="Description">Application Description</label>
</div>
<div class="d-flex flex-row-reverse bd-highlight">
<input type="submit" value="Submit" class="btn btn-primary mt-2" />
</div>
</form>

ASP.NET MVC 4 Entity Framework can not insert record

I get the following error when I try to add a Schedule.
The column name 'Doctor_id' is specified more than once in the SET clause or column list of an INSERT. A column cannot be assigned more than one value in the same clause. Modify the clause to make sure that a column is updated only once. If this statement updates or inserts columns into a view, column aliasing can conceal the duplication in your code.
Here is my schedule model
[Table("Schedule")]
public class Schedule
{
public int Id { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime Date { get; set; }
[Required]
[DataType(DataType.Time)]
public TimeSpan StartTime { get; set; }
[Required]
[DataType(DataType.Time)]
public TimeSpan EndTime { get; set; }
public bool Booked { get; set; }
public int Doctor_id { get; set; }
//public virtual Doctor Doctor { get; set; }
}
Here is my controller:
public ActionResult CreateSchedule(Schedule schedule)
{
TimeSpan startTime = schedule.StartTime;
TimeSpan endTime = schedule.EndTime;
db.Schedules.Add(schedule);
db.SaveChanges();
}
This is the form
<div class="form-horizontal">
<h4>Schedule</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<input type="hidden" name="Doctor_id" value="#Session["doctorid"]" />
<div class="form-group">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new { htmlAttributes = new { #class = "form-control date" } })
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StartTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StartTime, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.StartTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EndTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EndTime, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.EndTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
I have a hidden input name Doctor_id with value for the create form.
Please help me with this, thanks.

Getting CheckList data in MVC6 post

I am doing user roles in MVC6 (using EF7), and I am think I am just missing something, but on a form used to define a user roles I get nothing in the posted back Model to the controller
This is my Model
public class UserRoleItem
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public IdentityUserRole<int> userRole { get; set; }
public bool HasRole { get; set; }
}
public class UsersRolesViewModel
{
public int UserId { get; set; }
public string FullName { get; internal set; }
public List<UserRoleItem> UserRoles;
}
This is the view
#model Skill.ViewModels.Manage.UsersRolesViewModel
<br />
<h3>Set Roles for user - #Model.FullName</h3>
<form asp-action="ChangeUsersRoles" >
<div class="form-horizontal">
<hr />
<input type="hidden" asp-for="UserId" />
#foreach (var userRole in Model.UserRoles)
{
<input type="hidden" asp-for="#userRole.Id" />
<div class="form-group">
<div class="inline-block col-md-8">
<span class="col-md-1" align="center">
<input type="checkbox" asp-for="#userRole.HasRole" />
</span>
<div class="col-md-7">
#userRole.Name (#userRole.Description)
</div>
</div>
</div>
}
<hr />
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
This is the Controller
// GET: Users/ChangeUserRoles/5
public async Task<IActionResult> ChangeUserRoles(int? id)
{
if (id == null)
{
return HttpNotFound();
}
var model = new UsersRolesViewModel();
ApplicationUser appUser = await _context.ApplicationUsers.SingleAsync(m => m.Id == id);
if (appUser == null)
{
return HttpNotFound();
}
else
{
model.UserId = (int)id;
model.FullName = appUser.FullName;
var some = from r in _context.Roles
from ur in _context.UserRoles
.Where(inner => r.Id == inner.RoleId && inner.UserId == id)
.DefaultIfEmpty()
select new UserRoleItem
{
Id = (int)r.Id,
Name = r.Name,
Description = r.NormalizedName,
userRole = ur, // this is needed else it has a hissy fit
HasRole = (ur != null)
};
// get all of the Roles and then also link to the ones the user currently has
model.UserRoles = (some).ToList();
}
return View(model);
}
// POST: Users/ChangeUserRoles/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ChangeUserRoles([Bind(include:"UserId,UserRoles")]UsersRolesViewModel userModel)
{
if (ModelState.IsValid)
{
// update based on the changes
// return RedirectToAction("Edit", new { userModel.UserId });
}
return View(userModel);
}
So when I get the post back on Save, the UserRoles list is null, so I assume I am just missing an obvious thing here?
Also another small issue is the EF Linq statement. If I remove the
userRole = ur,
statement from the Select portion of the Linq query, the system has a fit and says my schema is out of date (which it isn't). I think it is due to the following statement where I am testing the outer join value
HasRole = (ur != null)
Although this seems perfectly reasonable and works if the ur variable is used prior to testing for null (or not)
After entering this question - I further investigated the issue and found that I could do what I needed using an EditorTemplate
So I created the EditorTemplate Folder under my Users View folder as it was a UsersController and then added the following UserRoleItem.cshtml file
#model UserRoleItem
<input type="hidden" asp-for="Id" />
<div class="form-group">
<div class="inline-block col-md-8">
<span class="col-md-1" align="center">
<input type="checkbox" asp-for="HasRole" />
</span>
<div class="col-md-7">
#Model.Name (#Model.Description)
</div>
</div>
</div>
I then changed the view (called ChangeUsersRole.cshtml) to be
#model Skill.ViewModels.Manage.UsersRolesViewModel
<br />
<h3>Set Roles for user - #Model.FullName</h3>
<hr />
<form asp-action="ChangeUsersRoles">
<div class="form-horizontal">
<input type="hidden" asp-for="UserId" />
#Html.EditorFor(m => m.UserRoles)
<hr />
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
Note also: that I tried using the new format
<input asp-for="UserRoles" />
instead of this line in the view
#Html.EditorFor(m => m.UserRoles)
But it did not work as expected. Again maybe I am still doing something wrong - or maybe that feature isn't working yet?

Post complex model to controller MVC using Facebook application template C#

I have following model:
class HomePageModel
{
public User user { get; set; }
public ResultHistory resultHistory { get; set; }
public Option option { get; set; }
public HomePageModel()
{
}
}
Code from controller when passing it into view:
[FacebookAuthorize]
public async Task<ActionResult> Index(Context context)
{
ViewBag.AppUrl = GlobalFacebookConfiguration.Configuration.AppUrl;
if (ModelState.IsValid)
{
var user = await context.Client.GetCurrentUserAsync<MyAppUser>();
var option = new Option();
//CODE for reading user from db, simpified
Users dbUser = db.Get(context);
var resultHistory = new ResultHistory(dbUser.NSPGW, dbUser.NSPGL,
dbUser.NMPGW,dbUser.NMPGL,dbUser.NDPGW, dbUser.NDPGL);
HomepageModel homepageModel = new HomepageModel();
homepageModel.option = option;
homepageModel.resultHistory = resultHistory;
homepageModel.user = user;
return View(homepageModel);
}
}
Code from controller
#using (Html.BeginForm("Start", "Home", FormMethod.Post, new { id="opcijeForm"}))
{
<div class="row">
<div class="col-md-4">
<div class="radio">
<label>
<input type="radio" name="radio" value="sp" />SP
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="radio" value="mp" />MP
</label>
</div>
<div>
<input type="submit" value="start" />
</div>
</div>
<div class="col-md-8">
<div id="spoption">
#Html.DropDownListFor(m => m.option.sl, Model.option.slSelectList)
<label style="padding-left:10px">
<input type="checkbox" id="bb" /> BB
</label>
#Html.DropDownListFor(m => m.option.swt, Model.option.swtSelectList, new {id="bbdd" })
<label style="padding-left:10px">
<input type="checkbox" id="ziv" /> ziv
</label>
#* #Html.DropDownListFor(m => m.gameOption.sln, Model.option.slnSelectList, new { id="zivdd"})*#
</div>
<div id="mpoption">
<label>Numer of oppointment</label>
#Html.DropDownListFor(m=>m.option.spn, Model.option.spnSelectList)
#Html.DropDownListFor(m=>m.option.smv, Model.option.smvSelectList)
</div>
</div>
</div>
}
and receiving model on post
[FacebookAuthorize]
[HttpPost]
public ActionResult Start(HomepageModel model)
{
//Some code
//here is for example model.option null
}
When I submit form with above model, in my controller action where I receive same model, all it's properties are null.Each class that is within HomePage has only string and int as properties. If I move something, for example from class Option and put it in HomePageModel direct, then properties I have moved are not null. Is there a way to post model as above, or should I just copy properties from these three class into HomePageModel class?
[EDIT]
It is because of meta-data FacebookAuthorize, when I remove it everything is working
MVC app facebook passing object from view to controller at submit

Upload in MVC4, got 2 parameters in my action but file is empty

I'm trying to upload a file to a directory. The following code worked for me
CONTROLLER
[HttpPost]
public ActionResult Index(HttpPostedFileBase uploadFile)
{
//string path = #"C:\Users\thomas\Desktop";
if (uploadFile != null)
{
string filePath = Path.Combine(Server.MapPath("/files"), Path.GetFileName(uploadFile.FileName));
uploadFile.SaveAs(filePath);
}
return RedirectToAction("Index");
}
HTML PAGE
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<form action="/Post/Index" method="post" enctype="multipart/form-data">
<label for="uploadFile">Upload file: </label>
<input name="uploadFile" id="uploadFile" type="file" />
<input value="uploadFile" type="submit" />
</form>
Now i'm trying to implement this in a function where i create a message which is created by a model that is containing a message and an item class. When i submit the form the model is passed to my savecontroller but the file is null in my parameter controller.
HTML PAGE
Create new message
#model GeoCitytroopers.Models.MessageItemModel
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Event</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Message.MessagePicture)
</div>
<div>
<label for="uploadFile">Upload file: </label>
<input name="uploadFile" id="uploadFile" type="file" />
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Message.MessagePicture)
#Html.ValidationMessageFor(model => model.Message.MessagePicture)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Item.ItemTitle)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Item.ItemTitle)
#Html.ValidationMessageFor(model => model.Item.ItemTitle)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Item.ItemDescription)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Item.ItemDescription)
#Html.ValidationMessageFor(model => model.Item.ItemDescription)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
CONTROLLER
[HttpPost]
public ActionResult Create(HttpPostedFileBase uploadFile, MessageItemModel ViewModel)
{
if (ModelState.IsValid)
{
Utility ut = new Utility();
Item viewItem = ViewModel.Item;
Message viewMessage = ViewModel.Message;
if (uploadFile != null)
{
string filePath = Path.Combine(Server.MapPath("/files"), Path.GetFileName(uploadFile.FileName));
uploadFile.SaveAs(filePath);
}
//ADD USER TO ITEM
viewItem = ut.AddUserToItem(viewItem);
//ADD ITEM
viewItem.ItemCreateddate = DateTime.Now;
//ADD DISTRICT TO ITEM
viewItem.DistrictID = ut.GetUserDistrict();
db.Items.Add(viewItem);
//ADD LINK
viewMessage.Item = viewItem;
db.Messages.Add(viewMessage);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(ViewModel);
}
How can i pass the uploading file to my controller?
Thanks in advance!
You forgot set the correct enctype to the form. You cannot upload files without that:
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" })) {
...
}
Now the upload will work and your uploadFile parameter will not be null.
My initial guess is that the you created using Html helper doesn't have the necessary encrypt on it.
try using
using(#Html.BeginForm("action-name","controller-name",
FormMethod.Post, new { enctype="multipart/form-data"}){
}
with appropriate values for action-name and controller-name