ASP.NET MVC Core date only format is not working using DataAnnotation - asp.net-core

Following viewmodel used in a view is supposed to display a StartDate as, say 9/30/2015. But it is displaying as 9/30/2015 12:00:00 AM. How can I make it display without time while using DataAnnotaion? I know I can use #Model.StartDate.ToString("MM/dd/yyy") inside view to display date only. But that would mean you have to do it in every view that is using the following ViewModel:
ViewModel:
...
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime StartDate { get; set; }
...
UPDATE
The corresponding model class of the above ViewModel already has the following DataAnnotation that correctly creates the data type in SQL Server table as Date; and when you run a query on the corresponding table in SSMS it correctly displays the StartDate column's data with dates only, say, 9/30/2015 etc.)
Model
...
[DataType(DataType.Date)]
public DateTime StartDate { get; set; }
...
StartDate in the sql db is in fact Date only. Moreover, if I run a query on SSMS it correctly returns date only.

There are two solutions to your problem. As per your comments, you are currently using #Model.StartDate to display a date.
You can either do this:
#Model.StartDate.ToString("d")
Or, you can use a model based approach in your ViewModel and do this:
[DataType(DataType.Date)]
public DateTime StartDate {get;set;}
Then, in your view use:
#Html.DisplayFor(m => m.StartDate)

Related

Why this ASP.NET Core DataAnnotation works in ViewModel but not in Model alone

In my one ASP.NET Core app, a View is using following ViewModel. The underlying model of the ViewModel has an attribute StartDate. The model has DataAnnotion on StartDate but I'm not using the same DataAnnotation on the StartDate in ViewModel since I thought if DataAnnotation is in your Model then it gets aggregated to your viewmodels. And hence, the following View should display the StartDate as Date only. But the View is displaying StartDate as date and time, e.g. 9/30/2015 12:00:00 AM. On the other hand if I use DataAnnotation [DataType(DataType.Date)] on StartDate attribute in the ViewModel as well, the View correctly displays the StartDate as date only, say, 9/30/2015.
Question: Why DataAnnotation on the Model is not getting aggregated to ViewModel?
Model
...
[DataType(DataType.Date)]
public DateTime StartDate { get; set; }
...
ViewModel
...
public DateTime StartDate { get; set; }
...
View
...
#Html.DisplayFor(t => t.StartDate)
...
Some DataAnnotations are used by MVC, some are used by EntityFramework (others are used by other frameworks, so it's not just EF and MVC). Some are used by both. For instance, [Required] is used by both EF and MVC, but for different reasons. EF uses it to mean non-nullable. MVC uses it to mean "requires a value in the textbox". However, the DataType attribute and many other types are MVC only. I know it's confusing, and there seems to be no good reference for which annotations are for which technology.
And this is a good reason why you need separate data models from view models. You may need a particular annotation on your data model (like [Required]) but don't want it in your ViewModel (because you want to accept no value in a field, and supply the value in a code-behind, for instance...

MVC4 Code First Database type "Date"

I need a database column to be a date data type in a MS SQL Server. It's a requirement for the project, it cannot be datetime.
In my model I have:
[DataType(DataType.Date)]
public DateTime? RequestedCompletionDate { get; set; }
This still creates the column as a nullable datetime. Is there any way to make it date code first?
After a lot of research I finally figured out how to do it.
In my model rather than using the DataType attribute I used the column attribute. My model now looks like this:
[Column(TypeName="date")]
public DateTime? RequestedCompletionDate { get; set; }
If anyone is trying to do something similar, although I used TypeName="date", you should be able to set TypeName to anything you want as long as it is a valid SQL Server Data Type.

why does a nullable datetime trying to validate the date, when it is empty?

I am building an MVC 4 application. I have the following property
[Display(Name = "ExpiryDateLabel", ResourceType = typeof(Resources.Manage.PrereqDetail))]
public DateTime? ExpiryDate { get; set; }
in my View when i post it back with an empty value it says
The field Expiry Date: must be a date
why is that happening?
Looks like you are doing localization on ExpiryDate property and if you are using jQuery validation, you might wanna check following post explaining the solution to same problem.
How to fix regional settings for jQuery datepicker so it works in Firefox and IE7?

Computing value of field based on next row in SSIS

I have a contract table with BeginDate fields but no end date on a SQL Server 2000 database (cringe). I'm using an SSIS package designed in the 2008 environment to move data from this table into a staging db for a data warehouse. I need to compute the end date.
The end date is the next contract start date for the customer minus one day.
In anything but SQL Server 2000 this would be easy enough to do with a CTE. I used one strategy that used Row Number to merge to sets, even that won't work here.
My strategy will be to pull the dates through a datasource component. Something like this:
SELECT CustomerId, ContractStartDate FROM Contracts
Then, I'll use a script component and override the ProcessInput method to loop through the result set and add the end date as an output value.
This seems like a pathetic method, but given my constraints, is probably the best method. Can anyone think of any other options?
After some further research I found that it isn't possible to traverse the input buffer at will.
The solution is a bit counter-intuitive to the question. Instead of identifying and modifying the next row, the best you can do is modify the current row based on the previous value. This means that the data will need to be evaluated from the greatest date to the smallest date within the customer id.
For the sake of continuity, I'll keep my example within the context of the original question.
Assume we have are input data for the script component. Add a sort component to order the record set by CustomerID, then by ContractStartDate descending.
Then in the script component, add CustomerID and ContractStartDate as input and add ContractEndDate as an output value.
Override the Input0_ProcessInputRow. The code to do this is generated by default.
Add some properties to keep track of the previous start date and previous customer, and set the current row's end date value based on the previous row.
Your script will look something like this:
public DateTime? PreviousRowStartDate { get; set; }
public string PreviousRowCustomerID { get; set; }
public int KnownContractPeriod { get; set; }
int defaultContractPeriod = 12;
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
if (PreviousRowCustomerID == Row.CustomerID)
{
Row.ContractEndDate= PreviousRowStartDate.Value.AddDays(-1);
}
else
{
Row.ContractEndDate= Row.ContractStartDate.AddMonths(defaultContractPeriod).AddDays(-1);
}
PreviousRowCustomerID = Row.CustomerID;
PreviousRowStartDate = Row.ContractStartDate;
}
This breaks down when dealing with the very first contract (the customers latest). For this reason, I've included a default contract period.
This problem might actually come up to bite me, but it's difficult to say right now as most contracts here are 12 months in length.

Statistical query in SQL - is this possible with NHibernate LINQ?

I have an application that uses a few data warehousing principles such as dimensional modeling to do reporting on a fairly simple database.
An example (simplified) entity named Call looks like this:
public virtual long Id { get; set; }
public virtual string OriginatorNumber { get; set; }
public virtual string DestinationNumber { get; set; }
public virtual DateDimension DateDimension { get; set; }
A few of the properties of the real model have been removed as they are irrelevant. The simplified DateDimension looks like this:
public virtual long Id { get; set; }
public virtual DateTime Date { get; set; }
public virtual int DayOfMonth { get; set; }
public virtual int Weekday { get; set; }
There are a LOT more columns like this - they are prepopulated for the current decade by application setup. So each date in the entire decade has a row in this table, and each Call has a link to the date that it occured. This is all mapped in Fluent NHibernate and working fine.
If I want to do some reporting, I can do this easily with the improved NHibernate LINQ provider in 3.0. We would like to use LINQ for the improved maintainability it gives us, but if we really MUST, we'll consider HQL, ICriteria or even plain SQL.
So say I want to build a report that shows the number of calls from a certain number, divided by the day of the week they occur. I can do that easily this way:
var query = Calls
.Where(c => c.OriginatorNumber == "402")
.GroupBy(c => c.DateDimension.Weekday)
.Select(g => new { Day = g.Key, Calls = g.Count() } );
In this example, "Calls" is basically an IQueryable returned from NHibernates LINQ provider (Query) through a repository interface. The query above gives me the correct results, NHibernate Profiler shows me that the SQL is pretty optimal, all is well.
However, if I want to do something slightly more advanced, I get stuck. Say I want the average number of calls per weekday. Not too far from the above, right? I just need to figure out the number of unique dates each weekday has in the result set, divide the total number of calls by it, and we're all set - right? Well, no, this is where I start to hit the limitations of the NHibernate LINQ provider. With LINQ to objects I could construct a query to do it - something along the lines of
.Select(g => g.Count() / g.GroupBy(c => c.DateDimension.Date).Count());
However, this does not convert into the correct query when using it in NHibernate. Rather, it turns both .Count() calls in the above to the same count(*) of call records, so the result is always 1.
I COULD of course just query for each call, weekday and date as a new anonymous object, then do the math on the application side, but according to conventional wisdom, That's Just Wrong (tm). I could end up doing it in desperation, tho, even tho it means pain when the table grows to a million++ calls.
The below is an SQL query that gives me the result I am looking for.
select ss.Weekday, AVG(cast(ss.Count as decimal))
from
(
select dd.Weekday, dd.Date, COUNT(*) as Count
from Call c
left outer join DateDimension dd
on c.DateDimension_id = dd.Id
where c.OriginatorNumber = '402'
group by dd.Weekday, dd.Date
) ss
group by ss.Weekday
order by ss.Weekday
Is it possible to do this with the NHibernate LINQ provider? Or, if that is not possible, how close can I get before I have to let the application fetch the intermediary result and do the rest?
There are a lot of things you can't do with the LINQ provider. Using HQL or CreateCriteria is just something you'll have to accept with NHibernate.
I haven't tried it, but it looks like you should be able to do what you want to do using HQL or CreateCriteria (with DetatchedCriteria).
If you are desperate you can also fall back to plain SQL using CreateSqlQuery.