Bootstrap datepicker. Trouble binding: The value is not valid - c#

I'm having trouble binding a property of my model using bootstrap datepicker. I'm getting the following error:
The value DATE is not valid for DATEFIELD
This is how the property is defined in my model:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
public DateTime FechaDesignado { get; set; }
This is how the view is constructed:
<div class="form-group">
<div>
<input type="datetime" class="datepicker form-control" asp-for="#item.FechaDesignado"/>
<span asp-validation-for="#item.FechaDesignado" class="text-danger"></span>
</div>
</div>
Which translates to:
<div class="form-group" form="form1">
<div>
<input type="datetime" class="datepicker form-control" data-val="true" data-val-required="The FechaDesignado field is required." name="item.FechaDesignado" value="09/01/1901" />
<span class="text-danger field-validation-valid" data-valmsg-for="item.FechaDesignado" data-valmsg-replace="true"></span>
</div>
</div>
This is how it looks on my DB.
This is the code for datepicker:
<script type="text/javascript">
$(function () {
$('.datepicker').datepicker({
"autoclose": true
});
});
</script>
Post Action inside the Controller:
[HttpPost, ActionName("Management")]
//[ValidateAntiForgeryToken]
public async Task<IActionResult> Management(int? id)
{
var storetoupdate = _context.Stores.SingleOrDefault(m => m.StoreID == id.Value);
if (await TryUpdateModelAsync(
storetoupdate, "item",
s => s.StoreName, s => s.IncomePeriodicity, s=>s.Usuario, s => s.FechaDesignado))
{
await _context.SaveChangesAsync();
return RedirectToAction("Management");
}
return RedirectToAction("Management");
}
Question: Seems like I must convert the date input field to a datetime object using DateTime.ParseExact but I don't know how to edit the controller for this. Sorry but I'm learning all this.
Thanks.

You can use DateTime.ParseExact for convert date format to datetime. Please see this for more information.
Edit
You can use data-format attribute like this for post correct format date:
<input data-format="0:MM/dd/yyyy" type="datetime" class="datepicker form-control" asp-for="#item.FechaDesignado"/>

Related

ASP.Net Core MVC how to post unknown number of fields against strongly-typed model

Totally stumped on this. I have a page where users can click an "Add Step" button, and some javascript appends rows with additional inputs from a <template> tag to a form. When debugging from the controller, the values are empty.
I looked at the following posts, but neither answer seem to help here (not sure if it's because I'm using .Net core - probably not):
Get post data with unknown number of variables in ASP MVC
Passing data from Form with variable number of inputs - MVC 5
Model (Procedure.cs)
public class Procedure
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public int MinNumber { get; set; }
public int MaxNumber { get; set; }
}
Controller (ProceduresController.cs)
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([FromForm]List<Procedure> model)
{
if (ModelState.IsValid)
{
foreach(var field in model)
{
// Database things will happpen eventually, but at this point the Count = 0
}
}
return View(model);
}
Currently the Create action signature includes the [FromForm] attribute, but I have no idea if that's required here. I also tried List<Procedure> model.
And the View (Create.cshtml)
I've stripped out a lot of the UI and javascript to make things easier to read
#model List<Procedure>
/* also tried #model Procedure */
#{
ViewData["Title"] = "Create Procedure";
ViewData["Sidebar"] = "App";
}
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="All" class="field-validation-summary"></div>
<div class="builder">
<div class="field-row">
<div class="field-group">
<label class="field-label">Instruction Name</label>
<input type="text" name="Name" class="field type:text" placeholder="Enter an instruction name" />
</div>
<div class="field-group">
<label for="Type" class="field-label">Instruction Type</label>
<select id="Type" name="Type" class="field type:select stretch">
/* removing for brevity */
</select>
</div>
</div>
<div class="field-row">
<div class="field-group">
<label class="field-label">Minimum Number</label>
<input type="number" name="MinNumber" class="field type:number" />
</div>
<div class="field-group">
<label class="field-label">Maximum Number</label>
<input type="number" name="MaxNumber" class="field type:number" />
</div>
</div>
</div>
<div class="field-row">
<div class="field-group">
<div class="add-step">Add Step</div>
</div>
</div>
<div class="field-row">
<div class="field-group">
<input type="submit" value="Submit Procedures" class="button button-submit" />
</div>
</div>
</form>
<template id="template">
<details class="accordion" open>
<summary>Procedure Step</summary>
<div class="details-content">
<div class="field-row">
<div class="field-group">
<label class="field-label">Instruction Name</label>
<input type="text" name="Name" class="field type:text" placeholder="Enter an instruction name" />
</div>
<div class="field-group">
<label for="Type" class="field-label">Instruction Type</label>
<select id="Type" name="Type" class="field type:select stretch">
/* removing for brevity */
</select>
</div>
</div>
<div class="field-row">
<div class="field-group">
<label class="field-label">Minimum Number</label>
<input type="number" name="MinNumber" class="field type:number" />
</div>
<div class="field-group">
<label class="field-label">Maximum Number</label>
<input type="number" name="MaxNumber" class="field type:number" />
</div>
</div>
</div>
</details>
</template>
#section Scripts {
#{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
<script>
const modal = new Modal();
function getParent(element, selector) {
for (; element && element !== document; element = element.parentNode) {
if (element.classList.contains(selector)) {
return element;
}
}
return null;
}
this.Builder = function () {
this.template = document.querySelector('#template');
this.builder = document.querySelector('.builder');
this.addStep = document.querySelector('.add-step');
this.clone = null;
this.counter = 0;
this.addStep.addEventListener('click', this.add.bind(this));
};
Builder.prototype = {
add: function () {
this.counter++;
this.clone = document.importNode(this.template.content, true);
this.builder.appendChild(this.clone);
// i'm doing things here to set the new field attribute values - removed for brevity
}
};
let builder = new Builder();
builder.add();
</script>
}
In the javascript do I need to set the new field name values a specific way? Should they look like <input type="text" name="Name[index]"> or <input type="text" name="#Model.Procedure[index].Name">?
I tried both but the Count is still 0 when posting back. I've pretty much hit a wall, so I appreciate any and all help.
.NET requires a little more effort for model binding on complex types. Naming of elements is important.
<input name="model[index].Name" />
<input name="model[index].Type" />
<input name="model[index].MinNumber" />
<input name="model[index].MaxNumber" />
The naming convention to bind is: Name of the parameter in your controller (model), index, property name. This will properly pass all objects to your list.
The same is true if you are passing objects to a list inside your model.
For example
public class Example {
public int Id { get; set; }
public List<Procedure> Procedures { get; set; }
}
in this case we just need to tell .NET what property you are mapping too.
<input name="model.Procedures[index].Name" />
In some cases you may need to also add a hidden field for the index: https://www.red-gate.com/simple-talk/dotnet/asp-net/model-binding-asp-net-core/

ASP.NET core 2.2 Unhandled exception when creating a form

I am currently creating a web application that takes in a new user, adds their information to a list, and then displays the users. When I follow the link to my form with validation (a form I have used many times before in other projects) I am getting an unhandled exception.
Here is the specific error code
AspNetCore.Views_Home_RegisterNewUser.<ExecuteAsync>b__12_0() in RegisterNewUser.cshtml, line 15
To this point, I have double checked that the model is correct and has the correct validation. I have made sure the controller and action are correct.
Here is the page for the form
#{
ViewData["Title"] = "RegisterNewUser";
}
<h1>RegisterNewUser</h1>
#model Lab20.Models.RegisterUser
#Html.ValidationSummary()
<form asp-controller="Home" asp-action="ListAllUser" method="post" class="bg-dark">
<div class="col-12">
First Name:
<input type="text" name="FirstName" value="#Model.FirstName" placeholder="#Model.FirstName" class="col-5" />
#Html.ValidationMessageFor(m => m.FirstName)
</div>
<div class="col-12">
Last Name: <input type="text" name="Last Name" value="#Model.LastName" placeholder="#Model.LastName" class="col-5" />
#Html.ValidationMessageFor(m => m.LastName)
</div>
<div class="col-12">
Birthday: <input type="datetime" name="Birthday" value="#Model.Birthday" placeholder="#Model.Birthday" class="col-5" />
#Html.ValidationMessageFor(m => m.Birthday)
</div>
<div class="col-12">
Email: <input type="text" name="Email" value="#Model.Email" placeholder="#Model.Email" class="col-5" />
#Html.ValidationMessageFor(m => m.Email)
</div>
<div class="col-12">
Password: <input type="text" name="Password" value="#Model.Password" placeholder="#Model.Password" class="col-5" />
#Html.ValidationMessageFor(m => m.Password)
</div>
<div class="col-12">
Favorite Color: <input type="text" name="FavoriteColor" value="#Model.FavoriteColor" placeholder="#Model.FavoriteColor" class="col-5" />
#Html.ValidationMessageFor(m => m.FavoriteColor)
</div>
<input type="submit" value="Add User" />
</form>
Here is the HomeController
public class HomeController : Controller
{
List<RegisterUser> listOfUsers = new List<RegisterUser>() { };
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult RegisterNewUser()
{
return View();
}
[HttpPost]
public IActionResult RegisterNewUser(RegisterUser newUser)
{
if (!ModelState.IsValid)
{
return View(newUser);
}
else
{
return View("AddNewUser", newUser);
}
}
public IActionResult AddNewUser(RegisterUser user)
{
listOfUsers.Add(user);
return View("Index");
}
public IActionResult ListAllUsers()
{
return View();
}
}
I would like my page to firstly, display, secondly, catch the validation I have added, and thirdly take the new user's information and display it in the ListAllUsers View.
<form asp-controller="Home" asp-action="RegisterNewUser" method="post" class="bg-dark">
</form>
your form post action will be in RegisterNewUser method, you're pointing it wrong in ListAllUsers.
hope, you get it
You form is posing to the action ListAlluser in the controller Home. Now according to your code, you don't have an action method by that name.
The correct asp-action parameter should be RegisterNewUser. So the code becomes
<form asp-controller="Home" asp-action="RegisterNewUser" method="post" class="bg-dark">
</form>

Specify a format for "asp-for" HTML Tag (ASP.NET Core)

In an ASP.NET Core project I have to display a (readonly) date in a specific format (say "dd/mm/yyyy HH:MM")
<div class="form-group">
<label asp-for="Date" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Date" readonly class="form-control" />
</div>
</div>
How can I do it, knowing that the Date field is declared in the model like this
public DateTime Date { get { return this.Timestamp.DateTime; } }
?
Try this.
<input asp-for="Date" asp-format="{0:dd/MM/yyyy HH:mm}" readonly class="form-control" />
Alternatively, you could decorate the property with DisplayFormatAttribute.
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy HH:MM}")]
public DateTime Date { get { return this.Timestamp.DateTime; } }
The markup you have would not need to change.
If it is read only, you could hardcode as -
<input value="#Model.Date.ToString("dd/MM/yyyy HH:mm")" readonly class="form-control" />
Or display as text
<div class="form-group">
<label asp-for="Date" class="col-md-2 control-label"></label>
<div class="col-md-10 form-control-static">
#Model.Date.ToString("dd/MM/yyyy HH:mm")
</div>
</div>
Using ASP.Core TagHelpers as per your question;
[DataType(DataType.Date)]
public DateTime Date { get { return this.Timestamp.DateTime; } }
will format the input fields nicely in accordance with your locale setting.
I haven't found a tag helper solution for any other tags, looks like hardcoding as per Win's answer

Telerik UI for MVC => DateTime bug

I am working with Telerik (Kendo) UI for ASP.NET MVC and I am using grid. The problem is that I have bug with DateTime type. Here source:
This is a part from my model:
public class Discussion
{
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime Date { get; set; }
// More code...
}
This is my editor template(which comes from Telerik UI)
#model DateTime?
<div style="background-color: red; color: aqua; font-size: 28px;">
#(Html.Kendo().DatePickerFor(m => m)
.Format("MM/dd/yyyy"))
</div>
And in view (in grid) this is for date property:
columns.Bound(model => model.Date).Width(150).Format("{0:MM/dd/yyyy}");
The problem is that after I create new element => http://prntscr.com/8iq7si
in my controller I receive date with value: {1.1.0001 г. 0:00:00} => http://prntscr.com/8iq8eq
In very rare cases the date is send, but than there is some bug with format and ModelState is never valid.
P.S Here what is generated html:
<input data-val="true" data-val-date="The field Date must be a date." data-val-required="The Date field is required." id="Date" name="Date" type="text" value="01.01.0001" data-role="datepicker" class="k-input" role="combobox" aria-expanded="false" aria-owns="Date_dateview" aria-disabled="false" aria-readonly="false" data-bind="value:Date" style="width: 100%;">

How to pass string object data to mvc controller for posting?

This is my code
<form class="form-horizontal formtext col-xs-12 col-sm-10 col-lg-10 row">
<div class="form-group">
<div class="col-xs-12 col-sm-5 col-lg-3 paddnone">
<label class="control-label">First Name</label>
</div>
<div class="col-sm-5" ng-if="!newRecord">
<input type="text" class="form-control" ng-model="userDetails.firstname" />
</div>
<div class="col-sm-5" ng-if="newRecord">
<input type="text" class="form-control" ng-model="userDetails.firstName" />
</div>
</div>
<div class="form-group">
<div class="col-xs-12 col-sm-5 col-lg-3 paddnone">
<label class="control-label">Last Name</label>
</div>
<div class="col-sm-5" ng-if="!newRecord">
<input type="text" class="form-control" ng-model="userDetails.lastname" />
</div>
<div class="col-sm-5" ng-if="newRecord">
<input type="text" class="form-control" ng-model="userDetails.lastName" />
</div>
</div>
<div class="form-group">
<div class="col-xs-12 col-sm-5 col-lg-3 paddnone">
<label class="control-label">Email Id</label>
</div>
<div class="col-sm-5" ng-if="!newRecord">
<input type="text" class="form-control" ng-model="userDetails.emailid" />
</div>
<div class="col-sm-5" ng-if="newRecord">
<input type="text" class="form-control" ng-model="userDetails.emailId" />
</div>
</div>
<div class="col-xs-12 col-sm-9 col-lg-7 btnbg">
<button class="btn btn-primary " ng-click="create(userDetails)">
SAVE
</button>
<button class="btn btn-primary ">
Cancel
</button>
</div>
$scope.create = function (userDetails) {
var userData = angular.toJson(userDetails);
return dataFactory.post("/Usercontroller/Save", userData)
.then(function (result) {
alert("save successfully");
});
public class UserDataModel
{
public UserDataModel ();
public Dictionary<string, string> Data { get; set; }
public string FormName { get; set; }
}
public async Task<JsonNetResult> SaveUser(string applicationId, dynamic user)
{
Dictionary<string, string> dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(user);
UserDataModel userDataModel = new UserDataModel ();
//userDataModel .Data = dict;
userDataModel.FormName = "one";
userDataModel = await Post<UserDataModel>(new UserDataModel{ Data = dict });
return new JsonNetResult { Data = userDataModel };
}
In the above code when i click save button data pass to create function in js,then the entire data convert to string and pass to mvc controller , but the dynamic user got object , now how to deserialze and store to webapi.
So you have two options here, 1) You should use razor cshtml instead
of html, it will ease your life. Following link will help you.
http://blog.michaelckennedy.net/2012/01/20/building-asp-net-mvc-forms-with-razor/
If you want to use existing html code:
a) You have to make the name of all fields same as your class object variable, it will automatically parse it to object when server side c# code got the control after form submission.
b) Make the parameter of c# form submission handler function to FormCollection
Following links will help you,
ASP.NET MVC 3 Razor: Passing Data from View to Controller
Deserialization:
var json = JsonConvert.DeserializeObject<dynamic>(sampleJson);
var data = ((JObject)json.data).Children();
Deserialize JSON with dynamic objects
Have your HTML code like this, using Razor Syntax
#using (Html.BeginForm("Upload", "ModelClass")
{
#Html.ValidationSummary(true)
//HTML elements which are based on your model class members.
}
In your controller class method, it would send this form data to the Upload Method.
[HttpPost]
public ActionResult Upload(ModelClass model)
{
//Send model to the model object to Model class for processing
return RedirectToAction("Upload");
}
EDIT: This method I have used in ASP.NET MVC 5 on Visual Studio community edition 2013.

Categories