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>
Related
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>
So right now if I want to change what partial view I display on a page based of off configuration I do the follow:
Config Item:
<add key="InstanceOwner" value="companyName" />
Call to render partial view:
<div id="" class="sidebarBox side-box3">
Html.RenderAction("ProductFeature", "Dashboard");
</div>
Controller ActionResult:
[OutputCache(Duration = 1)]
[ValidateInput(false)]
public ActionResult ProductFeature(string viewName = InstnaceOwner+"ProductFeature")
{
return PartialView(viewName);
}
I will name the partial views using a naming convention that is companyName-ProductFeature, the companies name will be variable. Doing it this way feels wrong and inefficient. I'm still really new to .NET MVC though and just want to know what the best approach to this is,Thanks!
the plan is to just change the value of the configuration key if I'm
having to change which instance (which customer) the app is being used
for
Based on that comment then it could just be as simple as reading the config value and use that to determine which view to show. You don't need to accept any parameters for the controller method.
public ActionResult ProductFeature()
{
var prefix = ConfigurationManager.AppSettings["InstanceOwner"];
return PartialView(prefix+"ProductFeature");
}
What version of MVC are you using?
If i was you, i will get all the data soon as i enter the page controller (e.g. HomeController)
public ActionResult Index()
{
var model = new SomeViewModel();
model.ProductFeature = InstnaceOwner + "ProductFeature"
return View(model);
}
Then in the View, (index.cshtml)
#Html.Partial("_ProductFeature", Model.ProductFeature)
and in the partial View (_ProductFeature.cshtml)
#model string
<span>Product Feature is #model</span>
Hope this answers your question
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);
}
Is it possible from a Controller to show a view, and then dependant on what that user selects in dropDownList - render another different view back in the original calling controller? Kind of a "daisy-chaining" effect.
The thinking behind this - is a user selecting a vehicle type - (associated with an ID number) in a view, back in the Controller dependant on what was chosen will render another view immediately displaying HTML according to the vehicle type they chose e.g. an HTML page for car or a boat or aeroplane etc...
If this is possbile can someone point me to a code examaple?
Actual Database Model below - but it is for documents, not vehicles!
check the method paremetares of your action method and return different views baed on that . Something like this.
public ActionResult GetInfo(string id,string vehicleTypId)
{
if(String.IsNullOrEmpty(vehicleTypeId))
{
var vehicle=GetVehicleType(vehicleTypId);
return View("ShowSpecificVehicle",vehicle) ;
}
var genericVehicle=GetVehicle(id);
return View(genericVehicle);
}
EDIT : Saying so, I seriously think you should keep those in 2 seperate Action methods. That makes your code clean and better readable. You may move the common functionality to a function and call if from bothe the action methods id needed. So i would do it in this way
Assuming you have a ViewModel for the first page( displays all vehicletypes)
public class VehicleTypesViewModel
{
//other relevant properties
public IEnumerable Types { set;get;}
public int SelectedTypeId { set;get;}
}
Your GET request for the initial view will be handled by this action result.It gets all the Vehicle types and return that to your view in the ViewModels Types property.
public ActionResult VehicleTypes()
{
VehicleTypesViewModel objVM=new VehicleTypesViewModel();
objVM.Types=dbContext.VehicleTypes.ToList();
return View(objVM);
}
and in your View called VehicleTypes.cshtml,
#model VehicleTypesViewModel
#using(Html.BeginForm())
{
#Html.DropDownListFor(Model.SelectedTypeId,new SelectList(Model.Types,"Text",Value"),"Select")
<input type="submit" value="Go" />
}
Another Action method to handle the form post. You have the selected type id here and you can get the specific details here and return a different view
[HttpPost]
public ActionResult VehicleTypes(VehicleTypesViewModel model)
{
// you have the selected Id in model.SelectedTypeId property
var specificVehicle=dbContext.Vehicles.Where(x=>x.TypeId=model.SelectedTypeId);
return View("SpecificDetails",specificVehicle);
}
Alternatively you can do a Get request for the specific vehicle using RedirecToAction method. I would prefer this approach as it sticks with the PRG pattern.
[HttpPost]
public ActionResult VehicleTypes(VehicleTypesViewModel model)
{
int typeId=model.SelectedTypeId;
return RedirectToAction("GetVehicle",new {#id=typeId});
}
public ActionResult GetVehicle(int id)
{
var specificVehicle=dbContext.Vehicles.Where(x=>x.TypeIdid);
return View(specificVehicle);
}
With Javascript : You can do a get call to the new view from your javascript also. without the HTTPpost to controller. You should add some javascript in your initial view for that
#model VehicleTypesViewModel
//Include jQuery library reference here
#Html.DropDownListFor(Model.SelectedTypeId,new SelectList(Model.Types,"Text",Value"),"Select")
<script type="text/javascript">
$(function(){
$("#SelectedTypeId").change(){
window.location.href="#Url.Action("GetVehicle","Yourcontroller")"+"/"+$(this).attr("id");
});
});
</script>
I think to get a better user experience create a partial view, and load that partial view in a div in the same page via an ajax call.
public ActionResult GetVehicalInfo(string id, string vehicleType)
{
var vehicle = GetVehicleType(id, vehicleTypId);
return PartialView("vehicle);
}
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.