How to check null value in MVC view? - asp.net-mvc

I am using MVC with LINQ-to-SQL class.
as foreign key can be null, i have one record having f.k. null and others are having values.
now i am displaying it in view by Index view.
In index view i am resolving f.k. by writing code like
<%= Html.Encode(item.UserModified.UserName) %>
Now i have a problem in view that "object reference is not set".
And this is because of we are having null value in one of the f.k. field!
so can i write code in view to check whether Associated object pointing to null or nothing?

You can write any code you want in the view if necessary, so you could do:
<%= Html.Encode(item.UserModified.UserName ?? string.Empty) %>
You could also make a HtmlHelper extension to do this:
public string SafeEncode(this HtmlHelper helper, string valueToEncode)
{
return helper.Encode(valueToEncode ?? string.Empty);
}
You could then simply do:
<%= Html.SafeEncode(item.UserModified.UserName) %>
Of course if it's UserModified that's null and not UserName then you'll need some different logic.

With C#, you can use the conditional operator:
<%= Html.Encode(item.UserModified == null ? "" : item.UserModified.UserName) %>
However, it might be a better choice to move the UserName property to be a direct child of item, or to put it in ViewData.

First consider whether in your model an instance of User is valid without Name. If no then you should put a guard clause in the constructor.
Secondly, too many and duplicated null checks is a code smell. You should use the refactoring Replace Conditional with Polymorphism. You can create a Null object according to the Null Object Pattern.
This will make sure that you do not have to check for Null everywhere.

Related

Is this by design in MVC Model Binding?

A simple scenario that I've never seen before, but a colleague has just hit - MVC3
Create an action method MyAction(int myProperty = 0)
Create a model that has a property MyProperty
Pass an instance of this model to a strongly typed view, but set the property to 10 in code (don't use the query string parameter!)
In the view, Html.TextBoxFor(x => x.MyProperty)
This should render 10 in the text box.
Now call the action method MyAction?myProperty=8
Shouldn't this still render 10 in the text box?
I see that I can override the property discovered by the expression and assume this is because they are the same name (Query String parameter and model property). Eveything is then in the ViewData but one overrides the other.
Is this by design?
This is by design - ModelState is the highest priority value-provider for model properties, higher than even model itself. Without query string parameter, ModelState does not contain value for MyProperty, so framework uses model value.
You can use ModelState.Remove("MyProperty") to ensure using model value
If you look at the source code for Html.TextBoxFor you will see that if a value exists in ModelState then it will always use that value before any other.
string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName, format) : valueParameter), isExplicitValue);
If the value is in ModelState, then it doesn't matter what you set in code.

check nullable value object in razor view

I wanna check a string nullable value. But its not work? Plz, someone show me how?
<%= LDC.Helpers.DataHelper.GetLabel(LDC.Helpers.DataHelper.getTypeMaxGrossWU(), (int)item.MGW_unit) != null ? LDC.Helpers.DataHelper.GetLabel(LDC.Helpers.DataHelper.getTypeMaxGrossWU(), (int)item.MGW_unit): "" %>
Assuming GetLabel returns null your code should work, so it appears it does not return null. Check the function's return type to see what equality check you should use.
Also, it's worth saying that this kind of logic should be put into a ViewModel. Putting it into your view is dangerously close to having spaghetti code.

Return empty string using Linq to SQL - Related table with no rows - ASP.Net MVC

I have 1 to many relationship with the following tables - Person and Email. When using linq to sql and ASP.Net MVC, I'd like to show the first email or an empty string in my Person view using code like this:
<%= Html.Encode(Model.Emails.FirstOrDefault().EmailAddress) %>
In cases where there are no email rows, I receive a NullReferenceException. I can return null safe values from SQL by using a view or sproc, but I'd like to just stick with generic linq to sql objects bound to tables.
Model.Emails.Select(x => x.EmailAddress).FirstOrDefault() ?? string.Empty
<%= Html.Encode((Model.Emails.FirstOrDefault() ?? new Email { EmailAddress = string.Empty }).EmailAddress) %>
Would work, not super clean to read though.
My vote for:
Model.Emails.Select(z => z.EmailAddress).DefaultIfEmpty("zzz").FirstOrDefault();
I thought that you could do it all inside the FirstOrDefault, but I was wrong-o! However, I also forgot that when you use DefaultIfEmpty you can just call First().
Model.Emails.Select(z => z.EmailAddress).DefaultIfEmpty("zzz").First();
Of course, replace ZZZ with just "" (not string.empty, that is unnecessary), but it is nice to see those records where the default is being chosen explicity when you are first writing it.

mvc modelbinding

I have an Edit action/view for my User object, but only want a few fields to be editable.
I've set up the view to bind to the User object, and am using Html.EditorFor() for the few fields that I want to be editable.
I noticed in my User object on Post:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditUser(Mynamespace.User user)
{ }
that only the fields that I provided .EditorFor() controls for actually have any data.
I tried using Html.Hidden(Model.ID) for one of the fields that i didn't want to be editable, but it is null in the new User object created from model binding.
So, my question- How do I bind where only a couple of the fields should be editable?
Thanks!
It sounds like you probably want to start thinking about using a View Model that is specific to the form/input that you're dealing with. But in the short term, ....
You could bind to a FormCollection parameter instead and copy the values manually, OR...
you can use the TryUpdateModel method to populate this existing user object with the new data.
Here's the documentation for TryUpdateModel:
http://msdn.microsoft.com/en-us/library/dd470756.aspx
It's still possible for malicious users to send phony form-values that map to real properties on your model, so to protect against this (like an employee changing his salary property with a simple form hack) you can introduce an interface that contains the white list properties that you allow.
Here's an example:
public interface IUserEditableFields
{
string Username {get;set;}
string Email {get;set;}
}
//... in the controller action
if(TryUpdateModel<IUserEditableFields>(user)) {
//validation passed
//only Username and Email were editable
}
This is a good resource on how to do this:
http://css.dzone.com/news/aspnet-mvc-think-before-you-bi
Are you using the strongly-type helper for the hidden field or is it exactly like you've typed. If you've got it exactly as typed, then the name of the hidden field is the value of the id, not the name of the property on the model (ID). You might want to change it to:
<%= Html.Hidden( "ID" ) %>
or (if using strongly-typed helpers)
<%= Html.HiddenFor( m => m.ID ) %>
Ben's answer is largely correct, in that a ViewModel might be more appropriate, and short of that, TryUpdateModel can be used. However, I add that in that case, rather than requiring the domain object to implement a new interface, you use the overload TryUpdateModel<T>(T, string[]), which allows you to whitelist the updateable properties in a string array by name.

ASP.NET MVC, strongly typed views, partial view parameters glitch

If i got view which inherits from:
System.Web.Mvc.ViewPage<Foo>
Where Foo has a property Bar with a type string
And view wants to render strongly typed partial view which inherits from:
System.Web.Mvc.ViewUserControl<string>
like this:
Html.RenderPartial("_Bar", Model.Bar);%>
Then why it will throw this:
The model item passed into the dictionary is of type 'Foo'
but this dictionary requires a model item of type 'System.String'.
when bar is not initialized?
More specific: why it passes Foo, where it should pass null?
As #Dennis points out, if the model value is null, it will use the existing model from the view. The reason for this is to support the ability to call a partial view using a signature that contains only the partial view name and have it reuse the existing model. Internally, all of the RenderPartial helpers defer to a single RenderPartialInternal method. The way you get that method to reuse the existing model is to pass in a null value for the model (which the signature that takes only a view name does). When you pass a null value to the signature containing both a view name and a model object, you are essentially replicating the behavior of the method that takes only the view name.
This should fix your issue:
<% Html.RenderPartial( "_Bar", Model.Bar ?? string.Empty ) %>
Look at ASP.NET MVC source (HtmlHelper.cs -> RenderPartialInternal method -> line 258):
...
if (model == null) {
if (viewData == null) {
newViewData = new ViewDataDictionary(ViewData);
}
...
this is exactly your case. ASP.NET MVC uses the ViewData from your ViewContext
UPDATED:
Try this instead:
<% Html.RenderPartial("_Bar", Model.Bar ?? "Default" ); %>
If you pass null as the model to RenderPartial, then it will look at the original model, which is why the error says foo.
You'll need to make sure that bar is initialized to be an empty string instead of null.
Edit: #Arnis, look at the source code. It doesn't lie. You are passing null to the overload of RenderPartial. You are not passing Foo. Internally, the system uses the Model from your page's ViewContext (which is Foo) when you pass a null Bar to RenderPartial.
Though this has been answered, I ran across this and decided I wanted to solve this issue for my project instead of working around it with 'new ViewDataDictionary()'.
I created a set of extension methods:
https://github.com/q42jaap/PartialMagic.Mvc/blob/master/PartialMagic.Mvc/PartialExtensions.cs
I also added some methods that don't call the partial if the model is null, this will save a lot of if statements.
I created them for Razor, but a couple of them should also work with aspx style views (the ones that use HelperResult probably aren't compatible).
The extension methods look like this:
#* calls the partial with Model = null *#
#Html.PartialOrNull("PartialName", null)
#* does not call the partial if the model is null *#
#Html.PartialOrDiscard("PartialName", null)
There are also methods for IEnumerable models and the discard ones can also be called with a Razor lambda that allow you to wrap the partial result with some html.
Feel free to use them if you like.

Resources