should I be using an #html.renderpartial or #html.renderaction - c#

I'm trying to bring in my menu.
In my _Layout.cshtml page I have
<div class="wrapper">
<!-- Navigation -->
#Html.RenderAction("Navigation", "Nav")
The Nav Controller looks like this
public ActionResult Navigation()
{
var pages = pageRepository.Pages;
return View(pages);
}
The Navigation View Looks like this
#model IEnumerable<Site.Domain.Entities.Page>
#{
Layout = null;
List<Site.Domain.Entities.Page> pages = new List<Site.Domain.Entities.Page>();
foreach(var page in Model)
{
pages.Add(page);
}
}
#foreach (var link in Model)
{
if (link.ParentPage == "Home")
{
<li>#link.PageTitle</li>
<ul>
#foreach (var subLink in pages)
{
if (subLink.ParentPage == link.PageTitle)
{
<li>#subLink.PageTitle</li>
}
}
</ul>
}
}
The view works fine when I go to .../nav/navigation
What I'm trying to do is bring this into my _Layout page so that I can use it as my menu.
I continue to get an error with #Html.RenderAction("Navigation", "Nav")
The error says "The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments"
Should I be using this as a partial? What is the best way to go about this?
Thanks for any advice!

For what you're trying to do, #Html.RenderAction(..) is the correct call. RenderAction is ChildActionExtension and will need to add that attribute to the controller.
Your controller should look something like below. Note that you will want to return a PartialView as well.
[ChildActionOnly]
public ActionResult Navigation()
{
var pages = pageRepository.Pages;
return PartialView(pages);
}
The Render action does not return HTML, but rather adds the content to the response. With that, your view should look like:
#{#Html.RenderAction("Navigation", "Nav");}
Reference: http://msdn.microsoft.com/en-us/library/ee721274(v=vs.108).aspx

Because Html.RenderAction is a void and does not return a value, you need to "escape" the call with braces
#{Html.RenderAction("Navigation", "Nav");}
In your controller, you should return a partial view instead.
public ActionResult Navigation()
{
var pages = pageRepository.Pages;
return PartialView(pages);
}

Related

Partial page update ASP.NET Core MVC

In controller, method associated with page recieves ViewData from other part of the programme and displays the View like this
public IActionResult Index() {
ViewData["msg"] = Client.GetMessage();
return View();
}
How can I update page only partially if ViewData I need to display changed?
Though you didn't show the complete picture but from here I can suggest you to go for conditional razor syntax in your html.
For example:
<div>
#if(msg.Length>10){
<p>Too big message.</p>
}
else {
<p>#msg</p>
}
</div>

How to use div by its Id in MVC Controller?

I'm developing a new application in ASP.Net MVC (beginner) from old application which is in ASP.Net and have one query that How should I convert below line of code into new in MVC?
HTML:
<div runat="server" id="dvLogList"></div>
.cs:
dvLogList.InnerHtml = sb.ToString()
I need to set the StringBuilder appended string html code to as dvLogList innerhtml
You can strongly-typed your view.
As an example I have a model:
class DisplayModel
{
public string str { get; set; }
}
In my controller I will pass this model to my view:
public ActionResult Display()
{
DisplayModel model = new DisplayModel
{
str = sb.ToString()
}
return View(model);
}
The next step is to make my view strongly typed. To make this possible add this line to the top
#model DisplayModel // Most of the cases you need to include the namespace to locate the class
<div id="dvLogList">#Model.str</div> // now your model is accessible in view
In the end, why are we doing this?
This one has the advantage compared to using viewbag because there are cases that we need to postback data to our controller. The values from your view were automatically binded to your model (given that you declare the model in your action).
// model is automatically populated
public ActionResult Save(DisplayModel model)
{
}
For further knowledge, read this link I cannot spare more time to improve this answer Strongly Typed Views
In your controller, make use of ViewData (or ViewBag)
ViewData["dvLogList"] = "whatever content you want";
In your view you can call the ViewData wherever you need it:
<div id = "dvLogList" >
#(new HtmlString(ViewData["dvLogList"].ToString()))
</div>
Hope this helps.
You can do this by following way:
in your controller action that invokes this view:
public ActionResult Index()
{
ViewBag.HTMLContent = "your HTML Content";
return View();
}
In Index.cshtml view:
<div id="dvLogList">
#Html.Raw("#ViewBag.HTMLContent") /*assuming your content is HTML content not just string*/
</div>
Use below code :
//Controller Action
public ActionResult Index()
{
ViewBag.HTMLContent = "Your HTML Data";
return View();
}
//View page code
<div id="dvLogList">
#Html.Raw((String)ViewBag.HTMLContent)
</div>

MVC4 cshtml page function call

I need to display a value in an editable textbox on my mvc page when it first loads if it exists. I've got a function that will take care of getting the value that I need, but I need to pass in parameters from the current model to get what I need from the database.
The problem I'm having is getting this value into the textbox. What I tried was
cshtml:
#Html.TextBoxFor(model => model.AdjustedLiabilityAmount, new { #Value=OBS_LIB.BLL.JeopardyAssessment.JeopardyAssessment.GetLatestAdjustedLiabilityAmount(Model.DOTNumber, Model.LiabilityAmount))}
I get a red squiggly that "The name 'Value' does not exist in the current context"
So I tried a different technique I read about which was like this.
Controller:
public ActionResult Index()
{
ViewBag.AdjustedValue = OBS_LIB.BLL.JeopardyAssessment.JeopardyAssessment.GetLatestAdjustedLiabilityAmount(Model.DOTNumber, Model.LiabilityAmount);
cshtml:
#Html.TextBoxFor(model => model.AdjustedLiabilityAmount, new { #Value=ViewBag.AdjustedValue)}
This time I'm getting the red squiggly "The name 'Model' does not exist in the current context."
I'm sure I'm just missing something basic here as I'm new to MVC.
Any help is much appreciated.
Entire ActionResult Index:
public ActionResult Index()
{
ViewBag.AdjustedValue = OBS_LIB.BLL.JeopardyAssessment.JeopardyAssessment.GetLatestAdjustedLiabilityAmount(Model.DOTNumber, Model.LiabilityAmount);
var Report = new OBS_LIB.DTO.JeopardyAssessmentReport();
Report.Stage = 1;
Report.Status = "Active";
Report.ReportItems = OBS_LIB.BLL.JeopardyAssessment.JeopardyAssessment.GetJAReportItems(Report.Stage, Report.Status);
return View(Report);
}
You want to do something like this:
Class:
public class ModelClassHere {
public float Liability {get;set;}
}
Controller:
public ActionResult Index(ModelClassHere model) {
model.Liability = 10.00;
return View(model); // pass model to the view
}
View:
#Html.TextBoxFor(x => x.Liability) // 'x' can be anything
EDIT*
If you already have a model and need to pass one simple value:
Controller:
public ActionResult Index(ModelClassHere model, string otherValue) {
model.Liability = 10.00;
ViewBag.Liability = model.Liability;
return View(model); // pass model to the view
}
View:
<input type="text" id="otherValue" name="otherValue" value="#ViewBag.Liability.ToString()" />
You can use
#Html.TextBox("AdjustedLiabilityAmount", (Decimal)ViewBag.AdjustedValue)}
Or
#Html.TextBox("AdjustedLiabilityAmount", Model.AdjustedLiabilityAmount == null ? (Decimal)ViewBag.AdjustedValue : Model.AdjustedLiabilityAmount)}
In decimal type you put your the type that you need.
You need to pass your model in the
Controller
return view(myModelName);
make sure you have access to it in your controller.
also your view has to reference the model in the #model line at the top.
Finally to call the model it would be
view:
Model.myModelName

Value not being passed properly to controller from view

I have an MVC application that when a link is clicked a page needs to be displayed based on the same values on another page. I can't figure out why what's getting passed is null instead of the string. My code is below.
Controller:
public string searchQ
{
get { return (string)Session["searchQ"]; }
set { Session["searchQ"] = value; }
}
public ActionResult Index()
{
Session["InitialLoad"] = "Yes";
return View();
}
[HttpPost]
public ActionResult Index(string heatSearch)
{
ViewBag.SearchKey = heatSearch;
searchQ = heatSearch;
return View();
}
public ActionResult Index_Perm()
{
ViewBag.SearchKey = searchQ;
return View();
}
public ActionResult PartialMainLim(string heatSearch)
{
HomeModel C = new HomeModel();
ChemViewModel D = new ChemViewModel();
D = C.QueryResults(heatSearch);
return PartialView(D);
}
public ActionResult PartialMain(string heatSearch)
{
HomeModel C = new HomeModel();
ChemViewModel D = new ChemViewModel();
D = C.QueryResults(heatSearch);
return PartialView(D);
}
The code in the index view looks like this (this one works):
#if (ViewBag.SearchKey != null)
{
<div>
#Html.Action("PartialMainLim", "Home", (string)ViewBag.SearchKey)
</div>
}
And in the index_perm view:
#if(ViewBag.SearchKey != null)
{
<div>
#Html.Action("PartialMain", "Home", (string)ViewBag.SearchKey)
</div>
}
When I check the value of SearchKey in both views it is correct. However for the method "PartialMain" null gets passed instead of the string, despite SearchKey being correct. This all works for the other view though. What am I doing wrong?
When passing values back to controller you have basically two options:
Make a form
Pass it as part of the url
Get methods only accept url attributes while Post methods are able to handle form content as well.
From what you are trying to do I'd say you could use something like:
#Html.Action("PartialMain", "Home", new {heatSearch = (string)ViewBag.SearchKey})
this should create url looking like /Home/PartialMain?heatSearch=[content of SearchKey]
EDIT:
That will only pass the value given it is present in the ViewBag. You are getting it from the Session which is imho a terrible idea in MVC (which should be session-less). Please consider if you really need it there. Usually there are other ways to implement this.
There is no HttpPost handler in the controller when you click the index_perm view.
I think that problem is your session that would be null. One of principles of framework ASP.NET MVC is stateless. Using session in ASP.NET MVC quite horrible.
At the moment, I think you can quickly fixed it by using TempData that default using Session under the hood. You could have a look an outdated article for further digging up ViewData vs TempData

MVC 3 Multiple Forms Validation

Having read In ASP.NET MVC3, how should one render multiple PartialViews backed by multiple Models?, and some others, I still don't know the best way to go about validating multiple partial-view--forms--models on a page.
I don't doubt that whatever's compelling me to think of them as triples right now is the problem. All I ask is that the "why's" be comments and the answers be answers.
I have a view, "Editor", that does multiple render-actions that prefill some forms:
#{
Html.RenderAction("EditName", new { name = Url.RequestContext.RouteData.Values["ID"]});
}
#{
//returns EditColor partial view prefilled with this widget's color's properties
Html.RenderAction("EditColor", new { name = Url.RequestContext.RouteData.Values["ID"]});
}
So I have an EditColorFormModel that has something like (since I don't want extravagant color names)...
[StringLength(8)]
public String Name
{
get;
set;
}
And I have a POST action to accept the EditColorForm submit with something like...
if (!ModelState.IsValid)
{
return View("Editor", EditColorFormModel);
}
But if so, I get stack overflow. I guess that's because this model hits that RenderAction to start the loop. I tried RedirectToAction("Editor", EditColorFormModel), but the validation messages don't get to the summary helper under EditColor partial view, which I'm assuming is because the model does not hit the RenderAction after all. So does it, or doesn't it, and what should I do?
My own answer is that I didn't ask the right question, and that I need a complete isolated example of the problem. I left the model out because there's no logic there, it's got some properties with validation attributes applied.
Controller:
[ChildActionOnly]
public PartialViewResult ColorEditor(Int32 WidgetId)
{
return PartialView(new Models.WidgetColorModel() {
Id = WidgetId
//prefill whatever else on form
});
}
[ChildActionOnly]
public PartialViewResult DimensionEditor(Int32 WidgetId)
{
//same for dim
}
[HttpPost]
public ActionResult ColorEditor(Models.WidgetColorModel m)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("", "Something not Kosher-colored in Denmark");
return View("Editor", m);
}
}
[HttpPost]
public ActionResult DimensionEditor(Models.WidgetDimensionModel m)
{
//same for dim
}
View:
<body>
<div>
#{
Html.RenderAction("ColorEditor", new { WidgetId = Context.Request.Params["WidgetId"]});
Html.RenderAction("DimensionEditor", new { WidgetId = Context.Request.Params["WidgetId"]});
}
</div>
</body>
Partial Views (DimensionEditor is structured exactly the same):
#model MvcApplication2.Models.WidgetColorModel
#using (Html.BeginForm("ColorEditor","Home", FormMethod.Post))
{
#Html.ValidationSummary()
<span>Specialized color editor for Widget #Model.Id</span>
#Html.EditorForModel()
<input type=submit name= "ColSubmit" value="Sumbit" />
}
Top-level view does RenderAction
ChildAction controller executes
Top-level view does RenderAction for the second editor
ChildAction controller executes
I fill in a bad value on one of the forms and submit
HttpPost action method picks it up, adds error message, and tries to render the top-level view with the same model
Top-Level view does RenderAction
HttpPost action method picks it up again (in the words of Rick Perry, "...")
And the result is a stack overflow exception because the View("Editor") reenters the Editor(Model) action method with RenderAction which warns about merging the RouteValues.
My question, of course, is what to change/insert, based on what, and where (in the controller, stupid) to prevent the overflow.

Categories

Resources