How to convert selected datetime picker value to timespan in Blazor - time

When reading from the database it's getting a value. But when I tried to add a new time slot as time (want to convert this to timespan as the database field is declared as Time(7) so the format is hh:mm:ss:fffffff) I found it difficult to save that.
I tried datetimepicker, then I tried time also, but its getting error.
My model class:
public class Model
{
public short TimeSlotID { get; set; }
public TimeSpan FromTime { get; set; }
public TimeSpan ToTime { get; set; }
}
Timerazor.razor
<div class="row">
<div class="col">
<div id="datetimepicker-control">
<!--<input type="time" name="FromTime" value="#item.FromTime.ToString("hh mm tt")" /> -->
</div>
<div class="col">
<input type="time" name="FromTime" value="#item.ToTime.ToString("hh mm tt")" />
</div>
#code
{
// i dont know how to pass the timespan value while inserting the time. here.
int rows = timeslotdal.InsertTimeSlot(modeltimeSlot);
}
for inserting
public int Insert(Model model)
{
List<SqlParameter> parameters = new List<SqlParameter>()
{
new SqlParameter("#TimeSlotID", model.TimeSlotID),
new SqlParameter("#FromTime", model.FromTime),
new SqlParameter("#ToTime", model.ToTime),
};
return db.ExecuteNonQuery("storedproceduremodel", parameters);}
}

You cannot bind a <input type='time'> control to a C# TimeSpan directly, you will need to add an intermediate step of binding to a DateTime and then pass the time element of the value through to the TimeSpan property.
See https://stackoverflow.com/a/54869699/41403 for an example of how to do this.

Related

.net core razor page #Html.Displayfor showing a random number

I'm using .net core (.net 5) to create a calculator.
Here's my model:
public class VogelsRulePlusModel
{
[Required]
[Range(0,30)]
public double SpherePower { get; set; }
[Required]
[Range(-30,0)]
public double CylinderPower { get; set; }
[DisplayFormat(DataFormatString = "{0:0.00}")]
public double Result { get; set; }
}
To display the output of the calculation, I'm using the the following tag "helper"
<div class="form-group">
<label asp-for="Result" class="control-label">#Html.DisplayFor(m => Model.Result)</label>
</div>
For some reason, when the page renders, I get a random number.
Here's the html this tag "helper" creates:
<div class="form-group">
<label class="control-label" for="Result">6.00</label> <-- ??
</div>
Does anyone know why this is happening and how to make it stop?
UPDATE: I'm such a doofus...again, I had the wrong controller in here.
This is what I'm using for the view.
public IActionResult VogelsRulePlus(VogelsRulePlusModel baseCurve)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
baseCurve.Result = BaseCurve.VogelsRulePlus(baseCurve.SpherePower, baseCurve.CylinderPower);
return View(baseCurve);
}

Connecting Telerik Blazor Control to Entity and Ardalis.SmartEnum

Using SmartEnum's https://github.com/ardalis/smartenum to handle Entity Framework 5.0 fields for things such as State, Country, Etc.
public sealed class StatesEnum : SmartEnum<StatesEnum>
{
public static readonly StatesEnum NotSpecified = new StatesEnum("(Select One)", 0);
public static readonly StatesEnum Alabama = new StatesEnum("Alabama", 1);
public static readonly StatesEnum Alaska = new StatesEnum("Alaska", 2);
public static readonly StatesEnum Arizona = new StatesEnum("Arizona", 3);
public static readonly StatesEnum Arkansas = new StatesEnum("Arkansas", 4);
public static readonly StatesEnum California = new StatesEnum("California", 5);
...
}
I am creating a Blazor Component for creating a job posting in our company's job board that uses these SmartEnum field types as one of the values in the entity. In the component I am using Telerik's Blazor DropDownList https://docs.telerik.com/blazor-ui/components/dropdownlist/overview to handle the fields that use these SmartEnum values. I have it correctly displaying the enum text and values using this code:
<TelerikDropDownList Id="dropStates" Data="#StatesEnum.List" TextField="#nameof(StatesEnum.Name)" ValueField="#nameof(StatesEnum.Value)" #bind-Value="#JobPostingVM.StateId"></TelerikDropDownList>
I am attempting to directly connect my View Model class (JobPostingVM) to the drop down list instead of creating a separate property for the selected value but I run into issues with the code complaining that you cant cast a SmartEnum to a type of int. Looking for a elegant solution outside of setting a property to store each selected value in this long form.
I am a Support Engineer with Telerik on the UI for Blazor team. I did some testing with the described scenario and found that it will require using a value external to the model.
For example, use a selectedValue variable as shown in the Bind to a Model documentation. The selectedValue variable can be set in the OnInitializedAsync method. Let me provide an example of this below.
Example
In the example, I am using a person model that is bound to a form with a SmartEnum for the SelectedState property. I am also setting default values in the model so that it displays the binding on page load. Let's go over each below.
Person Model
The person class is a basic CLR object with default values set for the collection properties.
public class Person
{
// Added for test
[Required(ErrorMessage = "Select a state")]
public StatesEnum SelectedState { get; set; } = StatesEnum.Alabama; // Default Value
// Original properties
[Required(ErrorMessage = "Enter your first name")]
[StringLength(10, ErrorMessage = "That name is too long")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Enter your last name")]
[StringLength(15, ErrorMessage = "That name is too long")]
public string LastName { get; set; }
[Required(ErrorMessage = "An email is required")]
[EmailAddress(ErrorMessage = "Please provide a valid email address.")]
public string Email { get; set; }
public int? Gender { get; set; } = 4; // Default Value
[Required]
[Range(typeof(DateTime), "1/1/2020", "1/12/2030", ErrorMessage = "Value for {0} must be between {1:dd MMM yyyy} and {2:dd MMM yyyy}")]
public DateTime StartDate { get; set; }
[Required(ErrorMessage = "Choose the team and technology you want to work on")]
public string PreferredTeam { get; set; } = "Blazor"; // Default Value
}
The SelectedState SmartEnum
The selected state is a property dervid from the SmartEnum implementation.
public sealed class StatesEnum : SmartEnum<StatesEnum>
{
private StatesEnum(string name, int value) : base(name, value)
{
}
public static readonly StatesEnum NotSpecified = new StatesEnum("(Select One)", 0);
public static readonly StatesEnum Alabama = new StatesEnum("Alabama", 1);
public static readonly StatesEnum Alaska = new StatesEnum("Alaska", 2);
public static readonly StatesEnum Arizona = new StatesEnum("Arizona", 3);
public static readonly StatesEnum Arkansas = new StatesEnum("Arkansas", 4);
public static readonly StatesEnum California = new StatesEnum("California", 5);
}
Blazor Component
The custom form comonent then uses the OnInitializedAsync method to populate the model and set the selected value.
#page "/"
#using TBACS.DropDownListSmartEnumBinding.Models
<div class="container-fluid">
<div class='row my-4'>
<div class='col-12 col-lg-9 border-right'>
<div class="row example-wrapper">
<div class="col-xs-12 col-sm-6 offset-sm-3 example-col card p-4">
<EditForm Model="#person" OnValidSubmit="#HandleValidSubmit" class="k-form">
<DataAnnotationsValidator />
<fieldset>
<legend>User Details</legend>
<div class="form-group">
<label for="StatesDDL">
<span>Select State <span class="k-required">*</span></span>
</label>
<TelerikDropDownList Data="#StatesEnum.List"
#bind-Value="#selectedValue"
TextField="#nameof(StatesEnum.Name)"
ValueField="#nameof(StatesEnum.Value)"
Id="StatesDDL"
Width="100%">
</TelerikDropDownList>
</div>
<div class="form-group">
<label for="FNameTb">
<span>First Name <span class="k-required">*</span></span>
</label>
<TelerikTextBox #bind-Value="#person.FirstName" Width="100%" Id="FNameTb" />
</div>
<div class="form-group">
<label for="LNameTb">
<span>Last Name <span class="k-required">*</span></span>
</label>
<TelerikTextBox #bind-Value="#person.LastName" Width="100%" Id="LNameTb" />
</div>
<div class="form-group">
<label for="GenderDDL">
<span>Gender <span class="k-field-info">optional</span></span>
</label>
<TelerikDropDownList #bind-Value="#person.Gender" DefaultText="Select gender"
Data="#genders" TextField="Text" ValueField="Id"
Width="100%" PopupHeight="auto" Id="GenderDDL">
</TelerikDropDownList>
</div>
<div class="form-group">
<label for="EmailTb">
<span>Email <span class="k-required">*</span></span>
</label>
<TelerikTextBox #bind-Value="#person.Email" Width="100%" Id="EmailTb" />
</div>
</fieldset>
<fieldset>
<legend>Team Preferences</legend>
<div class="form-group">
<label for="StartDateDP">
<span>Start date <span class="k-required">*</span></span>
</label>
<TelerikDatePicker #bind-Value="#person.StartDate" Width="100%" Id="StartDateDP" />
</div>
<div class="form-group">
<label for="TeamDDL">
<span>Preferred Team <span class="k-required">*</span></span>
</label>
<TelerikDropDownList #bind-Value="#person.PreferredTeam"
DefaultText="Preferred team" Id="TeamDDL"
Data="#Teams" Width="100%">
</TelerikDropDownList>
</div>
</fieldset>
<ValidationSummary />
#if (ShowSuccessMessage)
{
<div class="alert alert-info">
Application form submitted Successfully, we will get back to you
</div>
}
<div class="text-right">
<TelerikButton ButtonType="#ButtonType.Button" OnClick="#CancelForm">Cancel</TelerikButton>
<TelerikButton ButtonType="#ButtonType.Submit" Primary="true">Submit</TelerikButton>
</div>
</EditForm>
</div>
</div>
</div>
</div>
</div>
#code{
Person person { get; set; }
bool ShowSuccessMessage { get; set; }
protected override Task OnInitializedAsync()
{
// Bind model on load
GetDefaultPerson();
return base.OnInitializedAsync();
}
async void HandleValidSubmit()
{
// implement actual data storage here
ShowSuccessMessage = true;
await Task.Delay(2000);
ShowSuccessMessage = false;
GetDefaultPerson();
StateHasChanged();
}
void CancelForm()
{
GetDefaultPerson();
}
// External selected value primitive
int selectedValue { get; set; } = 0;
void GetDefaultPerson()
{
// in reality you may be pulling data from a service or authentication logic
// not only for the form model, but also for the data sources below
person = new Person()
{
StartDate = DateTime.Now.AddDays(7)
};
// Get the selected value from the model.
selectedValue = person.SelectedState.Value;
}
IEnumerable<DropDownModel> genders = new List<DropDownModel>
{
new DropDownModel {Text = "female", Id = 1},
new DropDownModel {Text = "male", Id = 2},
new DropDownModel {Text = "other", Id = 3},
new DropDownModel {Text = "I'd rather not say", Id = 4}
};
List<string> Teams = new List<string>
{
"Blazor", "Python", "Ruby", "Java", "JavaScript", "Assembler"
};
}
Misc. Models
The other models for the example are built around the DropDown.
Menu Item
public class MenuItem
{
public string Text { get; set; }
public string Url { get; set; }
public List<MenuItem> Items { get; set; }
}
DropDownModel
public class DropDownModel
{
public int? Id { get; set; }
public string Text { get; set; }
}
Wrapping Up
I believe the example answers the question. From what I understand, it seems like the result is what you were hoping to avoid, unfortunately. Let me know if you have any additional questions.
I hope this helps! Thank you for developing with UI for Blazor.
Eric D. Rohler

How to bind a list of objects in ASP.NET Core MVC when the posted list is smaller than original?

Using "disabled" attribute on inputs on form does not post them, which is expected and wanted. However, if you prepare a form of 3 objects in a list, disable the first and third, and submit, the 2nd object appears in post header, but does not bind to the list correctly, because it has an index [1] instead of [0].
I understand how model binding works and why it does not bind the posted object that I want, but I don't know how else to describe the problem to get specific results that would lead me to my solution. Anything I search for leads to basic post and binding examples.
List inside the model I'm using:
public IList<_Result> Results { get; set; }
Class _Result has one of the properties:
public string Value { get; set; }
I fill up the list and use it in view like so:
#for (int i = 0; i < Model.Results.Count; i++)
{
...
<td>
<input asp-for="Results[i].Value" disabled />
</td>
...
}
I have checkboxes on form, which remove (with javascript) the "disabled" attribute from the inputs and thus allow them to be posted.
When I fill up the said list with 3 _Result objects, they are shown on form and all have the "disabled" attribute. If I remove the "disabled" attribute from the first two objects and click on submit button, I receive the Results list with first 2 _Result objects, which is as expected.
However, if I remove the "disabled" attribute only from the second _Result object (the first _Result object still has "disabled" attribute), the Results list comes back empty in my Controller method.
In my Form Data Header, I see this: "Results[1].Value: Value that I want posted", which means that post occurs, but list does not bind the object due to the index.
Any idea on how I can achieve that proper binding? Also, the reason I'm using "disabled" attribute is because I'm showing many results on a single page and want to only post those that are selected.
For getting selected items, you could try checkbox with View Model instead of using jquery to control the disable property.
Change ViewModel
public class ModelBindVM
{
public IList<_ResultVM> Results { get; set; }
}
public class _ResultVM
{
public bool IsSelected { get; set; }
public string Value { get; set; }
}
Controller
[HttpGet]
public IActionResult ModelBindTest()
{
ModelBindVM model = new ModelBindVM
{
Results = new List<_ResultVM>() {
new _ResultVM{ Value = "T1" },
new _ResultVM{ Value = "T2" },
new _ResultVM{ Value = "T3" }
}
};
return View(model);
}
[HttpPost]
public IActionResult ModelBindTest(ModelBindVM modelBind)
{
return View();
}
View
<div class="row">
<div class="col-md-4">
<form asp-action="ModelBindTest">
#for (int i = 0; i < Model.Results.Count; i++)
{
<input type="checkbox" asp-for="Results[i].IsSelected" />
<label asp-for="#Model.Results[i].IsSelected">#Model.Results[i].Value</label>
<input type="hidden" asp-for="#Model.Results[i].Value" />
}
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>

ASP.Net MVC 6 PartialView model binding confusion

Background
We need to submit model with items. For that purpose, we make this complex model:
public class PaymentViewModel
{
public decimal? Payment { get; set; }
public string Description { get; set; }
public List<SplittedPaymentViewModel> SplittedPayment { get; set; } = new List<SplittedPaymentViewModel>();
}
public class SplittedPaymentViewModel
{
public short SplittedPaymentId { get; set; }
public decimal? Payment { get; set; }
public string Description { get; set; }
}
For rendering html, we this two views, one regular: CreatePayment
#model ZevApp.ViewModels.Record.PaymentViewModel
...
<input class="form-control" asp-for="Payment" type="number" />
<input class="form-control" asp-for="Description" />
...
<div class="panel-body" id="SplittedPayments">
#foreach (var spItem in Model.SplittedPayment)
{
#Html.Partial("SplittedPaymentPartial", spItem);
}
...
</div>
And the other Partial: SplittedPaymentPartial
#model ZevApp.ViewModels.Record.SplittedPaymentViewModel
...
<input class="form-control" asp-for="Payment" type="number" />
<input class="form-control" asp-for="Description" />
...
As you can see, from the first view, we call partial view and pass them item by item form the SplittedPayment list.
Unexpectedly behavior
We run the code but unexpectedly behavior is occur:
Each partial view bind Payment and Description form parent PaymentViewModel, not from a passed item?
Does anybody know what is wrong?
Each view define model at the beginning of the file.
From the controller we return PaymentViewModel, and for a test, there are tree SplittedPaymentViewModels. But we can't see values from the items.
I found that problem was CreatePayment.cshtml (thanks to the people from MVC community). It doesn't provide any information about the spItem expression when invoking the partial view.
var savePrefix = ViewData.TemplateInfo.HtmlFieldPrefix;
for (var i = 0; i < Model.SplittedPayment.Count; i++)
{
ViewData.TemplateInfo.HtmlFieldPrefix = Html.NameFor(m => m.SplittedPayment[i]);
var spItem = Model.SplittedPayment[i];
#Html.Partial("SplittedPaymentPartial", spItem);
ViewData.TemplateInfo.HtmlFieldPrefix = savePrefix;
}
You can find full description on https://github.com/aspnet/Mvc/issues/4106

Razor view dropdown list for a model class in MVC3

I have two model class in MVC3 one for Services which have those properties
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public int ChildOf { get; set; }
It also have a DB table by Entityframework
Another model is Quata which have those properties
public int ID { get; set; }
public string Sender_Name { get; set; }
public string Description { get; set; }
.....
......
public Services Service_ID { get; set; }
It also have a DB table by Entityframework
I want to create a Razor(C#) view (for Quata) where user can send a quata by fill a html form but where i wanna show a dropdown list with Services ID as dropdown value and Services Name as dropdown text which is also come dynamically from the Services DB table .
My question is how i should create that dynamic dropdown list by #Html.DropDownListFor ? and send the selected data from that dropdown list to a Controller ?
Try this
Controller:
public ActionResult Create()
{
var Services = new Services();
Services.Load(); //load services..
ViewBag.ID = new SelectList(Services.ToList(), "Id", "Name");
return View();
}
[HttpPost]
public ActionResult Create(Quata Quata)
{
//save the data
}
A strong Typed View: (Using Razor)
#model Quata
#using (Html.BeginForm()) {
<fieldset>
<legend>Quata</legend>
<div>
#Html.LabelFor(model => model.Service_ID.ID, "Service")
</div>
<div>
#Html.DropDownList("ID", String.Empty)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
take a look at #Html.DropDownListFor
So say your viewmodel has a list of said Services.
Something that may work for you is the following (you may not need a for loop here, editor is supposed to eliminate that, but I had some weird binding issues).
In your top level view which points at your viewmodel (#model Quata, assuming Quata is your viewmodel) have this code :
#For i = 0 To Model.DropdownListInput.Count - 1
Dim iterator = i
#Html.EditorFor(Function(x) x.DropdownListInput(iterator), "EnumInput")
Next
In your Editor Template (create a subfolder under the view folder this dropdownlist will be in called editor templates and name the template whatever you desire, mine was EnumInput).
In your editor template, which should point at your model for Services (#model Services) have something like the following code (with substitutions for your appropriate variable names):
#<div class="editor-label">
#Html.LabelFor(Function(v) v.value, Model.DisplayName)
</div>
#<div class="editor-field">
#Html.DropDownListFor(Function(v) v.value, New SelectList(Model.ParamEnums, "ValueForScript", "EnumValue"), "--Please Select A Value--")
#Html.ValidationMessageFor(Function(v) v.value)
</div>
Replace the list with your list and the lambda values with yours (#Html.DropDownListFor(x => x.id, New SelectList(x.ServiceList, "ID", "Name"), "--Please Select A Value--") or something like that.
Note that this code is in VB, but it should provide a rough guide.

Resources