Why isn't my ViewBag setting available in my view? - asp.net-mvc

I have the following code in my HomeController's Index action, and the code below it in my layout. When I call up the Home/Index view, the UserName property isn't set, but I know it is set in my controller, as I examine the value with a breakpoint.
Controller:
public ActionResult Index()
{
ViewData.Add("UserName", User.Identity.Name);
return View();
}
View:
#{
if (User.Identity.IsAuthenticated)
{
<text>Hello </text>
#ViewBag.UserName <text> - </text>
#Html.ActionLink("Sign Out", "LogOff", "Account", null, new { style = "font-weight: bold;" })
}
}
EDIT: When I try the following view code, as suggested in answers below, I get a the compilation error: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'Display' but appears to have an extension method by that name.
I wonder if this is not some side effect of my nested layouts? The layout for the view cited is _ThreeColumn, and the layout for the latter is _Layout, set as default in _ViewStart.

First off, you should consistantly use viewbag or viewdata in both your controller and view, as it makes your code easier to understand.
public ActionResult Index()
{
ViewBag.Username = User.Identity.Name;
return View();
}
The real problem lies with #Html.Display you dont need the # symbol again. It should be as follows:
#ViewBag.UserName <text> - </text>

change #Html.Display("#ViewBag.UserName") to #ViewBag.UserName
also you can do below for more readability (inside controller)
ViewBag.UserName= User.Identity.Name;
#variableName in razor views automatically produces html encoded text. See below
---A razor view start---
#{
string name= "<b>Praveen</b>";
}
Hello #name
<br><br>
Hello #Html.Raw(name)
---A razor view end---
--output----
Hello <b>Praveen!!</b> ---automatically html encoded
Hello Praveen ---html produced as it is

Related

Adding a dropdown list outside or RenderBody call

I have a .NET MVC project with Razor views and I would like to implement search functionality that consists of a dropdown list, a text box and a search button.
The problem is that I would like to implement this search snippet in my _Layout.cshtml file outside of the #RenderBody() call. This means that the search functionality would be accessible on every page (it would be located at the very top right corner).
I'm trying to find out what is a good way of implementing this. I can get it to work but it would involve adding same code (do get dropdown values) to all controllers and actions.
ViewBag.States = new SelectList(db.States, "Id", "Name");
Is there a better way to implement this? It feels very repetitive to do it this way.
You can have a child action method which returns the partial view needed for your header and call this action method in your layout.
Create a view model for the properties needed.
public class AllPageVm
{
public int SelectedItem { set; get; }
public List<SelectListItem> Items { set; get; }
}
Now create an action method in any of your controller. Mark this action method with ChildActionOnly decorator.
public class HomeController : Controller
{
[ChildActionOnly]
public ActionResult HeaderSearch()
{
var vm = new AllPageVm()
{
Items = db.States
.Select(a => new SelectListItem() {Value = a.Id.ToString(),
Text = a.Name})
.ToList()
};
return PartialView(vm);
}
Now in the HeaderSearch.cshtml partial view, you can render whatever markup you want for your search header. Here is a simple example to render the dropdown. You may update this part to include whatever markup you want (Ex : a form tag which has textbox, dropdown and the button etc)
#model AllPageVm
<div>
<label>Select one state</label>
#Html.DropDownListFor(a => a.SelectedItem, Model.Items, "Select")
</div>
Now in your layout, you can call this child action method
<div class="container body-content">
#Html.Action("HeaderSearch", "Home")
#RenderBody()
<hr/>
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
Make sure you are calling PartialView method from the HeaderSearch child action method instead of View method. If you call View method, it will recursively call the same method and you will get a StackOverflow exception

How to send model from view to controller with HttpUtility.HtmlEncode

I want to send model's description from view to controller. But it is throw exception special character's warning again. I want to use HttpUtility.HtmlEncode in view without [ValidateInput(false)] in controller. It is possible ?
#model UserModel
#using (Html.BeginForm("CreateUser", "Home", FormMethod.Post))
{
#Html.TextAreaFor(HttpUtility.HtmlEncode(x => x.Description))
<button type="submit" id="btnCreate">Create</button>
}
Did you try to add [AllowHtml] attribute in your model ?
public class ViewModel
{
[AllowHtml]
public string Description { get; set; }
}
No, it isn't security bug. ASP.Net MVC has automatic HTML encoding. Razor also includes the Html.Encode method. Calling this method will be double-encoded. Therefore you can not use Html.Encode twice.

MVC5 How to do a post from partialview?

My partialview:
#model Alina_2017.Models.DropDownModel
<h2>Groepen</h2>
<div>
<div>
#using (Html.BeginForm("SelectGroup", "~/Controllers/WerkvormController"))
{
#Html.DropDownListFor(x => x.selectedItem, new SelectList(ViewBag.groepen, "id", "Naam"), "Select", new { #class = "form-control" })
<input type="submit" id="zoekgroep" value="Zoeken" />
}
</div>
</div>
My main view:
#model Alina_2017.Models.WerkvormModel
#{
ViewBag.Title = "Index";
}
#Html.Partial("~/Views/DropDown/Groepen.cshtml")
//More irrelevant html
My controller:
public ActionResult Index()
{
ViewBag.groep1 = convertWerkvorm(db.Werkvormens.Where(f => f.GroepenWerkvormID == 1).ToList());
ViewBag.groep2 = convertWerkvorm(db.Werkvormens.Where(f => f.GroepenWerkvormID == 2).ToList());
ViewBag.groep3 = convertWerkvorm(db.Werkvormens.Where(f => f.GroepenWerkvormID == 3).ToList());
setViewBags();
return View();
}
[HttpPost]
public ActionResult SelectGroup(DropDownModel model)
{
// the value is received in the controller.
var selectedItem = model.selectedItem;
Debug.WriteLine(selectedItem);
return View("Index");
}
I'm getting a HTTP Error 404.0 - Not Found. Is it possible to call an action from a different controller? The reason it's in a partial view is because I'm using two different models + I'll be using the partialview in multiple other views (at least once I get it to work).
Your controller's name is wrong.
Replace
#using (Html.BeginForm("SelectGroup", "~/Controllers/WerkvormController"))
with
#using (Html.BeginForm("SelectGroup", "Werkvorm"))
You can verify the actual post URL if you view your source in browser, or check network tab in the browser's development tools.
The second argument to the BeginForm() method is simply the name of the controller, not its file:
#using (Html.BeginForm("SelectGroup", "Werkvorm"))
{
}
You can post to any server-side action from anywhere. There's no limit based on how the view is rendered because once everything is rendered it's all just client-side markup no matter where it came from.
As a learning exercise, examine the actual rendered markup in your browser's debugging tools and see the URLs created for the forms. Regardless of how the partial views are arranged, which controller returned the view, what the models are, etc... It's all just HTML in the end. You can even manually write a simple .html file with a form on it which successfully posts to a server-side ASP.NET MVC action.

How to return a string in same view in mvc

I am trying return a string from controller to the same view in MVC
but its returning to a new view
Below is the code of my view:
#using (Html.BeginForm("Index2", "home", FormMethod.Post))
{
<label></label>
<input type="submit" value="Click Me" />
}
Below is the code of my controller:
public ActionResult Index2()
{
string _return = "Hello world";
return Content(_return);
}
how can I display "hello world" in the label
thanks.....
You can pass the value using Model objects or simply use ViewBag
public ActionResult Index2()
{
ViewBag.return = "Hello world";
return View("YourViewName");
}
In View
<label>#ViewBag.return</label>
Make the model type of your view string like this:
#model string
And use that string in your code like this:
The action told me to say #Model
Another way, if you want to display the content of an action method is to call Html.Action in your view:
#Html.Action("Index2")

unable to set layout page for a view

I have created a helloWorldController, for which I have created a index method
Here is the view code which is generated for me
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
and my _layout page is default ASP.NET MVC 4 layout.
But still I am getting blank page with the string returned from the Index method.
How can I enable _Layout page for a view?
If that screenshot is the actual code for your controller, you need to return ActionResult for each action method rather than string, e.g.
public ActionResult Index()
{
return View();
}
The View() return value will work provided that there is a view called Index.cshtml in either your Views\HelloWorld or Views\Shared folder. The convention is that you have a specific folder with the same name as your controller for all views specifically relating to that controller - in your case HelloWorld

Resources