Display Local Date/Time in ASP.NET MVC Razor View - asp.net-mvc

I have an ASP.NET MVC app. This app uses Razor as the view engine. I need to display a date/time to the user. My challenge is, the DateTime property on the model is in UTC time. I want to display the time as the user's local time. Currently, I have the following:
<div>
#if (Model.LastModifiedOnUTC.HasValue) {
Html.Raw(Model.LastModifiedOnUTC.ToString());
}
else {
<span>This record has not been updated</span>
}
</div>
I want to display the DateTime as something like "Wednesday, February 11, 2015 at 3:27 PM". However, I'm not sure how to do this. When I do the above, an empty string is printed. Which doesn't make any sense to me.
Thank you for any insights

One option is to use JavaScript.
in your View
<time>#Model.LastModifiedOnUTC.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)<time>
JS (my example with JQuery)
$("time").each(function (elem) {
var utctimeval = $(this).html();
var date = new Date(utctimeval);
$(this).html(date.toLocaleString());
})

You can use use following code in razor
<div>
#if (Model.LastModifiedOnUTC.HasValue) {
Html.Raw(Model.LastModifiedOnUTC.ToLocalTime().ToString());
}
else {
<span>This record has not been updated</span>
}
</div>

Related

Conditional statements using vue.js with html element

Im new to vue.js, and Im trying to do a simple if with a date field within my ASP.NET MVC project.
I've seen examples on vue tutorials where the condition is done in the js file, but Im not convinced that this would help me.
I currently have a date field in my ViewModel that has two drop downs. This is for an application form that asks a person how long have they lived at their address. They can select up to 11 months and 6+ years. I have a button that allows them to add another address. When you click this button, the viewModel for the date fields are repeated so they can add another one (stored in a List).
However I want to wrap this around a condition that says only if the date entered is less than 6 years then the button would appear. Like I said, at the min it is there always.
my code for the address and its button is:
<fieldset>
<legend>Please provide all your addresses in the last 6 years</legend>
#Html.EditorFor(m => m.PreviousAddresses)
</fieldset>
<button class="button">Add another previous address</button>
What im trying to do is something like v-if="PreviousAddress < 6" but I dont think thats right. Can someone help with the syntax?
EDIT: The validation works on the back end. Just need the client side to work with it:
[Minimum(72, ErrorMessage = "Please enter 6 years address history")]
public int TotalAddressHistoryInMonths
{
get
{
int totalMonths = CurrentAddress?.Duration?.TotalPeriodInMonths ?? 0;
if (PreviousAddresses != null)
{
foreach (ResidencyInputViewModel residency in PreviousAddresses)
{
totalMonths += residency?.Duration?.TotalPeriodInMonths ?? 0;
}
}
return totalMonths;
}
}
The solution you have appears to be correct, but can you post the rest of your code. Seeing the data object should help.

Bootstrap 3 Datepicker Months View Only

I have an ASP.NET MVC web app and trying to use Bootstrap 3 Datepicker for my "month/year" field like the one in demo here:
https://eonasdan.github.io/bootstrap-datetimepicker/#min-view-mode
In that demo, it only allows users to select "year" and "month". Not "days". I want the same functionality in my app. However, in my app, it works the same on first click but on succeeding clicks it shows the "days" selection view. Setting the viewMode to 'years' doesn't fix the problem.
My model is as follows:
public class FilterViewModel
{
public DateTime? StartMonthYear { get; set; }
...
My view is as follows:
<div class="col-sm-3">
#Html.TextBoxFor(model => model.StartMonthYear, new { #class = "month-picker" })
...
<script type="text/javascript">
$(function () {
$('.month-picker').datetimepicker({
viewMode: 'months',
format: 'MM/YYYY',
useCurrent: false
});
});
</script>
The problem is that viewMode only sets the initial view. However, it seems this particular library doesn't provide any way to actually restrict which views are available.
There's an alternate libary that I personally use, which does give you the ability. It's virtually a drop-in replacement, so you shouldn't have to change much to switch over. However, importantly, it provides minView/maxView options you can utilize:
$(function () {
$('.month-picker').datetimepicker({
startView: 'month',
minView: 'month',
format: 'mm/yyyy'
});
});
As you can see there's a few minor differences:
viewMode becomes startView. The view names are also singular month vs. months.
The formatting string is more similar to C# formatting, so you'd use lowercase mm and yyyy.
The default for this library is to use the current date/time, so there's no need for a separate useCurrent option. If you want to specify a different start date/time, you'd use initialDate.
I found a work around which works pretty well:
$(function () {
$('.month-picker').datetimepicker({
viewMode: 'months',
format: 'MM/YYYY',
useCurrent: false
});
$('.month-picker').on("dp.show", function (e) {
$(e.target).data("DateTimePicker").viewMode("months");
})
});
This is based on a reply found here.
This was a bug in the library and solved. I faced same problem and solved by simply downloading latest version.

What should be the standard coding pattern for Sitecore

Using Sitecore 8.0, MVC, VS2015
I managed to generate the footer content as desired, for a practice site, but would like to know the standard way of doing things. The question is simple, but tried to explain in detail. Please bear with that :)
Requirement: The footer should display Office addresses and they should be editable by the Content author.
Sitecore Template : Location, Telephone 1, Telephone 2, IsActive(type-checkbox).
Datasource : A folder with items of the above template.
Code:
public class FooterViewModel
{
public List<Sitecore.Data.Items.Item> Addresses { get; set; }
}
public class FooterController : Controller
{
public ActionResult Footer()
{
var datasource = RenderingContext.Current.Rendering.Item;
FooterViewModel viewModel = new FooterViewModel();
viewModel.Addresses = new List<Item>();
if(datasource != null && datasource.HasChildren && datasource.Children.Count > 0)
{
foreach(Item address in datasource.Children)
{
if (address["IsActive"] == "1")
viewModel.Addresses.Add(address);
}
}
return View("~/Views/Shared/Footer.cshtml", viewModel);
}
}
Rendering the html using a Sitecore Controller Rendering
cshtml:
#using Sitecore.Mvc
#using Sitecore.Mvc.Presentation
#model Democore.Models.FooterViewModel
<div>
#foreach (var address in Model.Addresses)
{
<div>
<h3>#Html.Sitecore().Field("Location", address)</h3>
<ul>
<li>
#Html.Sitecore().Field("Telephone 1", address)
</li>
<li>
#Html.Sitecore().Field("Telephone 2", address)
</li>
</ul>
</div>
}
</div>
<div>
<p>&copy Copyright #DateTime.Now.Year. All rights reserved</p>
</div>
Here are my questions. (..well all 3 are more or less similar)
How to better this code/structure (or) in which case might it fail.
I did not like the way I hardcoded the field names in controller &
cshtml. What if the author changes the field names. How to tackle
that.
How does it work in a real scenario, say for eg if author
wants to show a third phone number. Will they contact the developer?
Because that requires a change in design & code too right?
This is a very broad question and will probably get closed -but here are some tips!
You controller is fine as far as error handling goes. You really want to add a global error handler for your site. This is a good example of that: http://www.sitecorenutsbolts.net/2015/10/23/Rendering-Exception-Handling-The-Right-Way/
You have 2 options - use constants and field ID's not the names, not a great option but works. A better option would be to use an ORM/Wrapper to do that. Two good ones are Fortis and Glass Mapper - both are very good - I contribute to Fortis so that would be my recomendation.
Normally if the design of the component changes it will require development support. You could use something like BrainJock's Score or ZenGarden to build your site and then the editor has a lot more control. But still likely would need a developer.
Hope this helps. For some info on good Sitecore architecture look here: Sitecore Helix and Sitecore Habitat

Mvc Html.Label or Html.TextBox doesn't create

I'm making a test page for a project I'm working on and I've made desired progress so far but I'm trying to create TextBoxes from a model of List being passed to the view, however, the it seems to just ignore anything I have tried.
<form id="form1" runat="server">
<input id="btnsubmit" type="submit" name="Submit" onclick="Submit" />
<div id="divControls">
<% foreach (TextBox control in (this.Model as List<TextBox>))
{
Html.Label("lblLabel", control.Text);
Html.TextBox(control.ID, control.Text, new { id = control.ID, style = "width:50", name = "txt" + control.ID });
} %>
</div>
</form>
The List isn't null in the Controller on return. I don't have a clue at what the problem could be. If I throw a Something in the for loop it executes the appropriate number of times so why isn't it creating the labels or textboxes?
At first I thought it was that I'm adding them inside a form but I removed the form tags and it still didn't work so I really have no Idea, any help would be much appreciated. I'm relatively new to MVC.
[HttpPost]
public ActionResult Index(FormCollection form)
{
List<TextBox> controls = new List<TextBox>();
foreach (String Key in form.Keys)
{
if (Key.Contains("txt"))
{
TextBox textBox = new TextBox();
textBox.ID = Key;
textBox.Text = form.GetValues(Key)[0];
controls.Add(textBox);
}
}
return View("Index", controls);
}
Here's my Action encase it's helps.
Also encase I wasn't clear enough, I am adding controls to a form at runtime using JQuery and then that Action will be part of the submit so it must send the textboxes back to the view so they are not deleted.
Like I said I'm new to the whole MVC and Asynchronous thing so If there's a better way to do this, advice would be much appreciated.
Your not printing the html
<% foreach (TextBox control in (this.Model as List<TextBox>))
{%>
<%=Html.Label("lblLabel", control.Text)%>
<%=Html.TextBox(control.ID, control.Text, new { id = control.ID, style = "width:50", name = "txt" + control.ID })%>
<% } %>
Your code is looping through the controls and the Html.whaterever is returning a string but your not doing anything with it, just discarding it.
you also don't need to return a whole TextBox object. This is probably inefficient. Just return an struct or a class containing your data
Html.Label returns a string containing a <label> tag.
You're discarding that string.
You need to write it to the page by writing <%= Html.Whatever() %>.

DevExpress DateEdit using MVC

I have just started using the
<% Html.DevExpress().DateEdit()
control and i got it to work fine in my ASP.Net MVC application. The code is as shown below:
aspx page:
<% Html.DevExpress().DateEdit(settings =>
{
settings.Name = "EndDate";
settings.Properties.NullText = "dd/MM/yyyy";
settings.Properties.EditFormat = EditFormat.Custom;
settings.Properties.EditFormatString = "dd/MM/yyyy";
settings.Properties.DisplayFormatString = "dd/MM/yyyy";
settings.Date = Model.EndDate;
settings.Width = 100;
}
).Render();
%>
Above this code i have a reference to my javascript file (DateChanges.js) in this file i want to be able to do something like:
$(document).ready(function(){
$("#EndDate").change(function(){
//do whatever i want
});
})
I cant do this now cause using firefox i can see that the actual textbox that this datepicker assigns a value to has be named "EndDate_I". So my question is how can i easily do this since i want to be able to catch the change event of this control and play around with it in jQuery??
The DevExpress MVC Extensions offer their own infrastructure for the client-side processing needs (see the http://help.devexpress.com/#AspNet/CustomDocument6908 help topic to getting started).
It is necessary to handle the client-side ASPxClientDateEdit.DateChanged event, and retrieve the newly selected Date via the client-side ASPxClientDateEdit.GetDate() method. Use the retrieved js Date object for your additional needs:
<script type="text/javascript">
function OnDateChanged(s, e) {
var newDate = s.GetDate();
alert(newDate);
}
</script>
settings.Properties.ClientSideEvents.DateChanged = "OnDateChanged";
There is a rather long Blog post at http://kennytordeur.blogspot.com/2011/05/aspnet-mvc-where-is-clientid_10.html discussing your problem
( I think it is to long to have it pasted here, and the author deserves the credits )
following on from your comment on Mikhails's answer, there will be a property in the global namespace with the name of your control, so it's just like this:
CalculateDayDifference(s.GetDate(), EndDate.GetDate());
All the mvc controls do this, for some you might have to set the EnableClientSideApi property to start using them.

Resources