#Html.DisplayFor for Empty - asp.net-mvc

I am trying to display empty string when model.EndDate is 0
#Html.DisplayFor(modelItem => model.EndDate)
I tried
#Html.DisplayFor(modelItem => model.EndDate == 0 ? "" : model.EndDate.ToString())
and
#Html.Display("End Date",model.EndDate == 0 ? "" : model.EndDate.ToString())
both did not worked for me. Both of the displaying empty when data is available.

Do a conditional outside the DisplayFor:
#if (Model.EndDate != 0)
{
Html.DisplayFor(modelItem => model.EndDate)
}

You can't compare a datetime to 0 in asp.net.
error CS0019: Operator `==' cannot be applied to operands of type `System.DateTime' and `int'
A DateTime is a value type so it get a default value of DateTime.MinValue when it isn't set.
using System;
public class Test {
public static DateTime badDate;
public static DateTime goodDate = DateTime.Now;
public static void Main(string[] args) {
Console.WriteLine(goodDate == DateTime.MinValue ? "" : goodDate.ToString());
Console.WriteLine(badDate == DateTime.MinValue ? "" : badDate.ToString());
}
}

How about this one ?
DateTime dt;
if (DateTime.TryParse("Your Date", out dt))
{
//Now you have validated the date
//Your code goes here
}

I think you should make your model property be a nullable type. So for example if its type is DateTime then declare the property as a nullable DateTime:
public DateTime? EndDate { get; set; }
this way instead of a 0 date (whatever that means) you will have no value. This also makes sense especially if this model property is coming from the database and is nullable.
You can read more about the nullable types here: http://msdn.microsoft.com/en-us/library/2cf62fcy(v=vs.80).aspx

I didn't like the answers given above because adding IF Statements to everything just slows your system down, in my case i needed to display a default string value several times in each row of a list view when the class property was a null value.
So have a look at the MS Docs here:
DisplayFormatAttribute.NullDisplayText Property
The following example shows how to use the NullDisplayText to define a caption to display when the data field is null.
// Display the text [Null] when the data field is empty.
// Also, convert empty string to null for storing.
[DisplayFormat(ConvertEmptyStringToNull = true, NullDisplayText = "[Null]")]
public object Size;

Related

Type cast an generic enum T to its type of T

I am building an generic SelectListItem to be used with a dropdown. Trying to cast an Enum of type T to its type , but Iam missing something. LocalizedStringKeyFor complains that its getting two parameters but as I sees it ((typeof(T))status) is just one parameter????
public static SelectListItem BuildSelectListItem<T>(T status, T? selected) where T : struct, Enum
{
var pretext = LocalizedString.Get(LocalizedStringKeyHelper.LocalizedStringKeyFor((typeof(T))status));
return new SelectListItem()
{ Text = pretext, Value = ((int)Convert.ChangeType(status, typeof(T))).ToString(), Selected = selected.HasValue && EqualityComparer<T>.Default.Equals(status, selected.Value) };
}
Actually you do give "two" different parameters to LocalizedStringKeyFor
You pass typeof(T) "and" status (missing some comma's but ok).
I think you're kind of looking for a helper function like below; where you pass your "T" (as enum) as the enumerator and the "selected" as parameter.
public static string LocalizedStringKeyFor<T>(T? selected) where T : struct, Enum
{
return "Not a clue";
}
public static IEnumerable<SelectListItem> BuildSelectList<T>(T? selected) where T : struct, Enum
{
var values = new List<SelectListItem>();
foreach (T type in (T[])Enum.GetValues(typeof(T)))
{
values.Add(new SelectListItem()
{
Text = LocalizedStringKeyFor<T>(type),
Value = Convert.ToInt32(type).ToString(),
Selected = selected == null ? false : selected.GetValueOrDefault().Equals(type)
});
}
return values;
}
In the method above I don't have a clue what your LocalizedStringKeyFor does, so that's the answer "Not a clue" - but it uses your enum as T for listing all options and marking the "selected?" as selected option. If there is no selected present your first option will default to selected.
You want to pass your enum value as an int, therefor the Int32 conversion and beware that this method does not work with flagged enums (or at least combined flagged enums).
UPDATE: How to use;
You can use this function for instance like so (where Model.Role is of course your enum)
#Html.DropDownListFor(m => m.Role, _dropdownLists.BuildSelectListItem<Contracts.Roles>(Model.Role), new { #class = "form-control" })

Display only date and no time in mvc [duplicate]

I have the following razor code that I want to have mm/dd/yyyy date format:
Audit Date: #Html.DisplayFor(Model => Model.AuditDate)
I have tried number of different approaches but none of that approaches works in my situation
my AuditDate is a DateTime? type
I have tried something like this and got this error:
#Html.DisplayFor(Model => Model.AuditDate.Value.ToShortDateString())
Additional information: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
Tried this:
#Html.DisplayFor(Model => Model.AuditDate.ToString("mm/dd/yyyy"))
No overload for method 'ToString' takes 1 arguments
If you use DisplayFor, then you have to either define the format via the DisplayFormat attribute or use a custom display template. (A full list of preset DisplayFormatString's can be found here.)
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? AuditDate { get; set; }
Or create the view Views\Shared\DisplayTemplates\DateTime.cshtml:
#model DateTime?
#if (Model.HasValue)
{
#Model.Value.ToString("MM/dd/yyyy")
}
That will apply to all DateTimes, though, even ones where you're encoding the time as well. If you want it to apply only to date-only properties, then use Views\Shared\DisplayTemplates\Date.cshtml and the DataType attribute on your property:
[DataType(DataType.Date)]
public DateTime? AuditDate { get; set; }
The final option is to not use DisplayFor and instead render the property directly:
#if (Model.AuditDate.HasValue)
{
#Model.AuditDate.Value.ToString("MM/dd/yyyy")
}
I have been using this change in my code :
old code :
<td>
#Html.DisplayFor(modelItem => item.dataakt)
</td>
new :
<td>
#Convert.ToDateTime(item.dataakt).ToString("dd/MM/yyyy")
</td>
If you are simply outputting the value of that model property, you don't need the DisplayFor html helper, just call it directly with the proper string formatting.
Audit Date: #Model.AuditDate.Value.ToString("d")
Should output
Audit Date: 1/21/2015
Lastly, your audit date could be null, so you should do the conditional check before you attempt to format a nullable value.
#if (item.AuditDate!= null) { #Model.AuditDate.Value.ToString("d")}
Googling the error that you are getting provides this answer, which shows that the error is from using the word Model in your Html helpers. For instance, using #Html.DisplayFor(Model=>Model.someProperty). Change these to use something else other than Model, for instance: #Html.DisplayFor(x=>x.someProperty) or change the capital M to a lowercase m in these helpers.
You can use the [DisplayFormat] attribute on your view model as you want to apply this format for the whole project.
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public Nullable<System.DateTime> Date { get; set; }
#ChrisPratt's answer about the use of Display Template is wrong. The correct code to make it work is:
#model DateTime?
#if (Model.HasValue)
{
#Convert.ToDateTime(Model).ToString("MM/dd/yyyy")
}
That's because .ToString() for Nullable<DateTime> doesn't accept Format parameter.
For me it was enough to use
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime StartDate { set; get; }
I implemented the similar thing this way:
Use TextBoxFor to display date in required format and make the field readonly.
#Html.TextBoxFor(Model => Model.AuditDate, "{0:dd-MMM-yyyy}", new{#class="my-style", #readonly=true})
2. Give zero outline and zero border to TextBox in css.
.my-style {
outline: none;
border: none;
}
And......Its done :)
You could use Convert
<td>#Convert.ToString(string.Format("{0:dd/MM/yyyy}", o.frm_dt))</td>
In View Replace this:
#Html.DisplayFor(Model => Model.AuditDate.Value.ToShortDateString())
With:
#if(#Model.AuditDate.Value != null){#Model.AuditDate.Value.ToString("dd/MM/yyyy")}
else {#Html.DisplayFor(Model => Model.AuditDate)}
Explanation: If the AuditDate value is not null then it will format the date to dd/MM/yyyy, otherwise leave it as it is because it has no value.
After some digging and I ended up setting Thread's CurrentCulture value to have CultureInfo("en-US") in the controller’s action method:
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
Here are some other options if you want have this setting on every view.
About CurrentCulture property value:
The CultureInfo object that is returned by this property, together
with its associated objects, determine the default format for dates,
times, numbers, currency values, the sorting order of text, casing
conventions, and string comparisons.
Source: MSDN CurrentCulture
Note: The previous CurrentCulture property setting is probably optional if the controller is already running with CultureInfo("en-US") or similar where the date format is "MM/dd/yyyy".
After setting the CurrentCulture property, add code block to convert the date to "M/d/yyyy" format in the view:
#{ //code block
var shortDateLocalFormat = "";
if (Model.AuditDate.HasValue) {
shortDateLocalFormat = ((DateTime)Model.AuditDate).ToString("M/d/yyyy");
//alternative way below
//shortDateLocalFormat = ((DateTime)Model.AuditDate).ToString("d");
}
}
#shortDateLocalFormat
Above the #shortDateLocalFormat variable is formatted with ToString("M/d/yyyy") works. If ToString("MM/dd/yyyy") is used, like I did first then you end up having leading zero issue. Also like recommended by Tommy ToString("d") works as well. Actually "d" stands for “Short date pattern” and can be used with different culture/language formats too.
I guess the code block from above can also be substituted with some cool helper method or similar.
For example
#helper DateFormatter(object date)
{
var shortDateLocalFormat = "";
if (date != null) {
shortDateLocalFormat = ((DateTime)date).ToString("M/d/yyyy");
}
#shortDateLocalFormat
}
can be used with this helper call
#DateFormatter(Model.AuditDate)
Update, I found out that there’s alternative way of doing the same thing when DateTime.ToString(String, IFormatProvider) method is used. When this method is used then there’s no need to use Thread’s CurrentCulture property. The CultureInfo("en-US") is passed as second argument --> IFormatProvider to DateTime.ToString(String, IFormatProvider) method.
Modified helper method:
#helper DateFormatter(object date)
{
var shortDateLocalFormat = "";
if (date != null) {
shortDateLocalFormat = ((DateTime)date).ToString("d", new System.Globalization.CultureInfo("en-US"));
}
#shortDateLocalFormat
}
.NET Fiddle
Maybe try simply
#(Model.AuditDate.HasValue ? Model.AuditDate.ToString("mm/dd/yyyy") : String.Empty)
also you can use many type of string format like
.ToString("dd MMM, yyyy")
.ToString("d") etc
This is the best way to get a simple date string :
#DateTime.Parse(Html.DisplayFor(Model => Model.AuditDate).ToString()).ToShortDateString()
Instead of
#Html.DisplayFor(Model => Model.AuditDate)
Use
#Model.AuditDate.ToString("MM/dd/yyyy")
This style renders the date as: 06/02/2022.
You can style your string accordingly to how you need it.
I had a similar issue on my controller and here is what worked for me:
model.DateSigned.HasValue ? model.DateSigned.Value.ToString("MM/dd/yyyy") : ""
"DateSigned" is the value from my model
The line reads, if the model value has a value then format the value, otherwise show nothing.
Hope that helps
You can use this instead of using #html.DisplayFor().
#Convert.ToString(string.Format("{0:dd/MM/yyyy}", Model.AuditDate))
You just need To set Data Annotation in your Model.
[DisplayFormat(ApplyFormatInEditMode = true,DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime AuditDate {get; set;}
On view(cshtml page)
#Html.DisplayFor(model => model.AuditDate)
Nothing else you need to do.
Hope its useful.
See this answer about the No overload for method 'ToString' takes 1 arguments error.
You cannot format a nullable DateTime - you have to use the DateTime.Value property.
#Model.AuditDate.HasValue ? Model.AuditDate.Value.ToString("mm/dd/yyyy") : string.Empty
Tip: It is always helpful to work this stuff out in a standard class with intellisense before putting it into a view. In this case, you would get a compile error which would be easy to spot in a class.

Why Can't I Do This Foreach in MVC?

This is my controller action:
<EmployeeAuthorize()>
Function HRA_Table() As ActionResult
' get current employee's id
Dim db1 As EmployeeDbContext = New EmployeeDbContext
Dim user1 = db1.Tbl_Employees.Where(Function(e) e.Employee_EmailAddress = User.Identity.Name).Single()
Dim empId = user1.Employee_ID
Dim empSSN = user1.Employee_SSN
Dim hra = db.Tbl_HRAs.Where(Function(x) x.SSN = empSSN)
Return View(hra.ToList)
End Function
This is my model:
Public Class Tbl_HRA
<Key()> Public Property HRA_ID() As Integer
Public Property SSN() As String
Public Property Height() As Double
Public Property Weight() As Double
Public Property Nic_EE() As String
Public Property Nic_SP() As String
Public Property BMI() As Double
Public Property BP_S() As Double
Public Property BP_D() As Double
Public Property HDL() As Double
Public Property LDL() As Double
Public Property Tot_Chol() As Double
Public Property Continine() As String
Public Property Glucose() As Double
Public Property Waist() As Double
Public Property Hip() As Double
Public Property Triglycerides() As Double
Public Property A1C() As Double
Public Property LDL_HDL() As Double
End Class
This is my view:
#ModelType IEnumerable(Of GemcoBlog.Tbl_HRA)
#Code
Layout = Nothing
End Code
#For Each item In Model
#item.Height
Next
The error I get is:
The 'Height' property on 'Tbl_HRA' could not be set to a 'String'
value. You must set this property to a non-null value of type
'Double'.
I can't seem to understand why this error is occurring. I tried changing it to double based on some articles I read, but still it won't work!
Thanks for your help.
From your comment, it appears that the column in the table is a varchar. As a result, your model must define it as a string. Try changing the height property to be as follows:
Public Property Height() As String
Unfortunately, you can't do type conversions directly in the LINQ to SQL implementation. If you want, you could project into another type (in the Select clause), but you would still need the immediate fetch (context.GetTable(Of T)) to have the types be equivalent between your database and the model.
This article might be of use - looks like an issue with your database schema? Is this column set as nullable in table?
http://digitaltoolfactory.net/blog/2012/03/how-to-fix-yet-another-you-must-set-this-property-to-a-non-null-value-of-type-double-problem-with-entity-framework/
i think this will help you
<ul>
#For Each g As MvcApplication1.Genre In Model
#<li>#g.Name</li>
Next
</ul>
and also see this url for more help
http://www.asp.net/web-pages/tutorials/basics/asp-net-web-pages-visual-basic
It looks like this could be caused by this database. It looks like they set these to varchar instead of double which is not ideal.

LINQ Checking for Nulls

How do I check Nulls in Linq?
I have a third-party code that returns a DataTable with a column type DateTime that is nullable.
My code:
var profile = (from d in ds.Tables[0].AsEnumerable()
select new User
{
FirstName = d["FirstName"].ToString(),
Birthdate = Convert.ToDateTime(d["BirthDate"].ToString())
}).FirstOrDefault();
returns an error that the Object cannot be cast from DBNull to other types on the Birthdate= statement.
I tried using the following code but returns a cast exception (Cannot cast from string to DateTime?)
Birthdate = (DateTime?)d["BirthDate"].ToString();
Is there a way to short-hand checking the null values?
I have not tested this, but you can try the following:
Birthdate = d.Field<DateTime?>("BirthDate")
From MSDN:
The Field method provides support for accessing columns as nullable types. If the underlying value in the DataSet is [DBNull.]Value, the returned nullable type will have a value of null.
You can create a helper function to check the value for DBNull, as follows:
private static DateTime? ConvertNullableToDateTime(object val) {
return (val != null && val != DBNull.Value) ? Convert.ToDateTime(val.ToString()) : null;
}
Now you can use this method in your LINQ query:
var profile = (from d in ds.Tables[0].AsEnumerable()
select new User
{
FirstName = d["FirstName"].ToString(),
Birthdate = ConvertNullableToDateTime(d["BirthDate"])
}).FirstOrDefault();
I have got error while I used the above code. I think we can use the below code.
Birthdate = dr["BirthDate"] == DBNull.Value ? (DateTime?)null : (DateTime)dr["BirthDate"];
If we use Convert.ToString(dr["BirthDate"]), then it convert to empty string, if it has DBNull.
Try that also.

Storing string versions of database status values

I'm writing an ASP.NET MVC 3 site and I need to convert some integer values from the database that represent statuses with user readable strings, for example:
...
<td>
#item.Status
</td>
...
I've written an HTML Helper to do the conversion:
public static string MessageType(this HtmlHelper helper, int type)
{
string messageType = "Unknown";
switch((Types.MessageTypes)type)
{
case Types.MessageTypes.Join:
messageType = "Join App";
break;
case Types.MessageTypes.New:
messageType = "New App";
break;
}
return messageType;
}
And I'm storing the types as an enumeration in the Types class.
My question is whether there is a cleaner way to do this? I don't like these magic strings in my code and it creates numerous dependencies in different parts of the code.
Any thoughts?
Many thanks,
Sam
I usual decorate the enums with the DisplayAttribute like this.
enum MessageTypes
{
[Display(Name = "Join App")]
Join,
[Display(Name = "New App")]
New
}
Then I use a helper to extract them:
public static string EnumDisplay(this HtmlHelper helper, Enum model)
{
var enumType = model.GetType();
var modelValue = Convert.ToInt64(model);
var matches = from field in enumType.GetMembers()
where field.MemberType == MemberTypes.Field && Enum.IsDefined(enumType, field.Name)
let value = Convert.ToInt64(Enum.Parse(enumType, field.Name, false))
where modelValue == value
let attribute = field.GetCustomAttributes(typeof (DisplayAttribute), false).Cast<DisplayAttribute>().FirstOrDefault()
select attribute == null
? field.Name
: attribute.Name;
return matches.FirstOrDefault() ?? "Unknown";
}
Then you can do
#Html.EnumDisplay((MessageType)item.MessageType)
In my opinion, you should be storing the corresponding user readable strings in the database next to the integer. And return an object e.g. StatusViewModel to the view model. the View model may have >
class StatusViewModel
{
int type;
string displayMessage;
}
makes sense?

Resources