MVC3 - Model set to null but still entering IF statement - asp.net-mvc

I have a Model (BusinessPlaceDetailsViewModel) which has another Model (Hub) inside it.
However if I set my Hub to null it still enters my IF condition, see here:
I have tried loads of different combinations like putting each IF statement inside its own braces.
Why is it entering the If block?

I'm betting that it is a problem with the controller not passing the model down to the view.
If you post the controller code it might be helpful.

Just out of curiosity, can you try this and see if the h1 displays?
#if (!User.Identity.IsAuthenticated)
{
if (Model.Hub == null)
{
<h1>wtf shouldn't have gotten here</h1>
}
else
{
...
}
}

Could you handle your check in the controller first? If not maybe try .Any() with Ling.
#using System.Linq
#if( !Model.Any() )
{
...
}
else

I solved this problem by using the following in the BusinessPlaceDetailsViewModel
public BusinessPlaceDetailsViewModel()
{
Hub = new HubViewModel();
}

Related

check member existence in Mvc ViewBag

Sometimes I have to check the existence of a member inside the ViewBag from inside an Mvc View, to see if for any problem the action forgot to assign the member. Inside my Razor View I have:
#if(ViewBag.Utente.Ruolo.SysAdmin)
how can I check that ViewBag.Utente is defined?
You must check all objects are null or not. Utente, Utente.Ruolo and Utente.Ruolo.SysAdmin may be null:
#if (ViewBag.Utente != null)
{
if (ViewBag.Utente.Ruolo != null)
{
if (!string.IsNullOrEmpty(ViewBag.Utente.Ruolo.SysAdmin))
{
//ViewBag.Utente.Ruolo.SysAdmin has value..you can use it
}
}
}
As simple as this:
#if (ViewBag.Utente != null)
{
// some code
}
If you are using MVC4 you can use
#if (ViewBag.Utente != null)
For previous versions take a look at those answers:
Checking to see if ViewBag has a property or not, to conditionally inject JavaScript
You can you use it;
#if (string.IsNullOrEmpty(ViewBag.Utente.Ruolo.SysAdmin))
{
}
But if you want to check your users are confirmed or not, I think it is not a good way..

How can you use session variable to determine view?

I have my global.asax setup with the following Session_Start:
protected void Session_Start()
{
HttpContext.Current.Session.Add("sourceCode", "default");
}
On my controller I have the following:
public ActionResult Index(string sourceCode)
{
if (sourceCode != null && sourceCode != "default")
{
Session["sourceCode"] = sourceCode;
return View();
}
else
{
return View();
}
}
I want to be able to display different partial layouts based on this session variable. What is the proper way to do this? Can I load a partial view from the controller or do I need to handle that on the view?
This is a variable that I want to use site wide to determine special pricing and landing page creatives. Do I have to set this same structure up on every single controller or is there a more global way of doing this?
Thanks,
Brian
If you want to show the layout in all the pages, you might want to add the logic in the layout file. There, you will add something like that (assuming razor)
#if(HttpContext.Current.Session["someValue"]){
#*render some partial*#
}else{
#*render some other partial*#
}
By the convention of MVC, controller should decide which view it should open. For this in controller you have code like this:
public ActionResult Index(string sourceCode)
{
if (sourceCode != null && sourceCode != "default")
{
Session["sourceCode"] = sourceCode;
ViewData["PartialView"] = "partialviewname1";
}
else
{
ViewData["PartialView"] = "partialviewname2";
}
return View();
}
and in view you can write code something like this:
<div>
#Html.Partial(Convert.ToString(ViewData["PartialView"]))
</div>
and if you have decide which partial view you have to load on each and every request then you can write above logic in global action filter. Global action filter get executed before any requested action method. To know more about global action filter you can explore this link.
http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

Detecting a source view from the controller

Is it possible to recognize the view/page name from which a form was submitted to Action ?
For example, lets say I have two Views: AddInfo and EditInfo
Both views have a form that I would like to submit to
#Html.BeginForm("SaveInfo","Info")
{
...
}
Inside of the SaveInfo() method I would like to recognize whether the submit/request came from AddInfo or EditInfo view.
public ActionResult SaveInfo(FormCollection collection)
{
if(...I got here from AddInfo View) <----- ?
{
..do something
}
}
Is it possible ?
Thanks
If the Add/Edit forms are at different pages on your site, then you can use Request.UrlReferrer to check where it came from. That is, something like:
bool sourceIsAddForm =
(Request.UrlReferrer.AbsoluteUri.IndexOf("/add", StringComparison.CurrentCultureIgnoreCase) != -1);

Asp.Net MVC3 Redirect

I have an action like shown below. In GetAvailableBookList, I get the list and if there is not any available book redirect to a message page. But in action part code continues to execute and gets an exception and I find myself in error page.
I don't want to use return RedirectToAction or something like that because there are a lot of places where we use this redirect logic in our application.
public ActionResult ActionName()
{
List<BookType> bookList = GetAvailableBookList();
// some code
return View("RelatedView");
}
private List<BookType> GetAvailableBookList()
{
....
list = GetList();
if(list.Count == 0)
{
System.Web.HttpContext.Current.Response.Redirect(messagePageUrl, true);
}
else return list;
}
Unfortunately, Response.Redirect() isn't really friendly with ASP.NET MVC. My rule of thumb is if it comes from HttpContext I don't want to touch it in the controller (of course there are many exceptions to that rule) -- especially since it improves testability.
My suggestion is to use RedirectToAction, but since you don't want to repeat code you can do it in such a way that you don't have to repeat code (although in this case I don't see a problem with repeating code).
public ActionResult LoadBookListAndContinue(
Func<List<BookType>, ActionResult> continuation)
{
var list = LoadBooklist();
if(list.Any())
{
return action(continuation);
}
return new RedirectResult(messagePageUrl);
}
// in your controller
public ActionResult ActionName()
{
return LoadBookListAndContinue(
list => {
// some code
return View("RelatedView");
});
}
Is it pretty? No, but it works better than the Redirect exception.
Use
return RedirectToAction("NoListAvailable");
if you have a specific action you would like to execute. The NoListAvailable action can return a view indicating the problem.
Alternatively, you could return the view directly
return View("NoListAvailable");
The exception you are getting is probably ThreadAbortException and this is something you cannot avoid unless you allow the thread to continue (2nd argument in Response.Redirect).
On a side note your current solution is generally flawed. You should use RedirectToAction in each action when your method returns an empty list.
Throwing a specific exception and redirect where you catch it may be solution
Try to write
System.Web.HttpContext.Current.Response.Redirect(messagePageUrl, false);

If a key does not exist in the ModelState, how can I add it? aspnetmvc1

I am trying to create a workaround in my controller which handles a bug in ASP.NET MVC v1. The bug occurs if you post a listbox which has nothing selected (http://forums.asp.net/p/1384796/2940954.aspx).
Quick Explanation:
I have a report that accepts two dates from textboxes and one or more selections from a ListBox. Everything works except for validation if the listbox is left with nothing selected.
When the form posts and reaches my controller, the model contains all items necessary. However, the ModelState does not contain a key/value for the listbox. To resolve, I was hoping something like this would do the trick:
if (!ModelState.ContainsKey("TurnTimeReportModel.Criteria.SelectedQueuesList") || ModelState["TurnTimeReportModel.Criteria.SelectedQueuesList"] == null) {
ModelState.Keys.Add("TurnTimeReportModel.Criteria.SelectedQueuesList");
ModelState["TurnTimeReportModel.Criteria.SelectedQueuesList"].Equals(new List<string>());
}
Unfortuantely, this throws the following exception when I try to add the key:
System.NotSupportedException: Mutating a key collection derived from a dictionary is not allowed.
Any ideas?
Thanks in advance!
Use the ModelState.Add method directly:
ModelState.Add("TurnTimeReportModel.Criteria.SelectedQueuesList",
new ModelState{ AttemptedValue = new List<string>() } )
I ended up going with the following which has done the trick:
if (ModelState.ContainsKey("TurnTimeReportModel.Criteria.SelectedQueuesList") && ModelState["TurnTimeReportModel.Criteria.SelectedQueuesList"] == null) {
ModelState["TurnTimeReportModel.Criteria.SelectedQueuesList"].Value = new ValueProviderResult("", "", CultureInfo.CurrentUICulture);
} else if (!ModelState.ContainsKey("TurnTimeReportModel.Criteria.SelectedQueuesList")) {
ModelState.Add("TurnTimeReportModel.Criteria.SelectedQueuesList", new ModelState{Value = new ValueProviderResult("","",CultureInfo.CurrentUICulture)});
}

Resources