I am trying to dynamically render pages from database. The view looks like this
#model MyModel
#{
ViewBag.Title = Model.Title;
Layout = Layout = "~/Views/Shared/_PageInnerLayout.cshtml";
}
#MvcHtmlString.Create(Model.Content)
MyModel has just 3 properties; Id, Title and Content
If the Content has just HTML, the view renders just fine. But in some cases, I need to render partials too. So Content may contain code like
#{
Html.RenderPartial("_FooterPartial");
}
This does not work. Its being rendered literally, like shown in the image below
How do I fix this so that the page is rendered properly?
The problem is in the difference between Html.RenderPartial and Html.Partial helper methods. RenderPartial directly write the result to HttpContext.Response while Partial return it as a MvcHtmlString. You need to replace the RenderPartial with Partial and maybe the RenderAction with Action.
Edited:
You need to render the content if contains the razor view scripts. If so it means you are actually storing the views or partial views inside the database. You can create a new VirtualPathProvider to help loading the views from the database. For more information see ASP.NET MVC load the Razor views from database and ASP.NET MVC and virtual view
I tried doing this with VirtualPathProvider, but it didn't work.
Finally what I did was to write the Content from database into a temporary view and then render the view. It worked
public ActionResult DynamicPage(int id) {
var dynamicPage = new PagesContext().Pages.FirstOrDefault(s => s.Id == id);
string webroot = Server.MapPath("~").TrimEnd('\\');
string fileName = webroot + "\\Views\\\\Solutions\\Temp.cshtml";
System.IO.File.WriteAllText(fileName, dynamicPage.Content);
return View("Temp");
}
Here, the Content property of the dynamicPage containts HTML(including Razor code)
Related
I have a partial view for ViewBag.count, which is defined in the ShoppingCartController. The problem is that the ViewBag will only show when you are on the ShoppingCart View. I want the ViewBag to be seen on all views. How do I fix this? I am currently rendering the partial like this:
#Html.Partial("_ShoppingCart", new List<bytme.Models.ShoppingCartModel>())
The partial view called _ShoppingCart:
<span class="badge">#ViewBag.count</span>
You should create a seperate action method which returns HTML markup needed to render the cart section of your page and include that in all your view using Html.Action method.
You may also decorate this action method with ChildActionOnly attribute so that users's cannot directly access this action method by requesting the url /ShoppingCart/Cart.
[ChildActionOnly]
public ActionResult Cart()
{
ViewBag.ItemCount = 2; // replace hard coded value with your actual value
return PartialView();
}
and in your partial view (~/Views/Shared/Cart.cshtml), you may write the HTML code which is needed for the cart segment of the page.
<span class="mycart">
Total items in cart #ViewBag.ItemCount
</span>
Here we are using ViewBag to pass the item count numeric value from the action method to it's partial view. But you may use a view model and use the strongly typed view approach to pass data from your action method to the partial view (this is my preferred approach).
Now in other views/layout file where you want to render the cart HTML, you can call the Html.Action method
<div>
#Html.Action("Cart","ShoppingCart")
</div>
<h1>Welcome to my site</h1>
When razor execute your view, it will see this Html.Action method and that will be executed and the output of that (the HTML markup generated fro the action method), will be included in the final output generated for the current view.
I am using the PartialView method, so that it will not try to execute the Layout code. (People make this mistake and gets an infinite calls to the Cart action method.
For Asp.Net Core projects
If you want to do the same thing in asp.net core projects, you may use View components to achieve the same results.
Create a view component to render the cart.
public class CartViewComponent : ViewComponent
{
public IViewComponentResult Invoke(string name)
{
var totalItemCount = 3;
return View(totalItemCount);
}
}
Create a razor view for this view component with the name Default.cshtml inside ~/Views/Shared/Components/Cart directory and you can have your razor code/HTML markup inside that to render the desired HTML. In this example, I am using a strongly typed approach where my view is stongly typed to int type and I am passing an int value from the the Invoke method when calling the View method.
#model int
<span>
Total items : #Model
</span>
Now you can invoke this view component in other views/ layout file by calling the Component.InvokeAsync method.
<div>
#await Component.InvokeAsync("Cart")
</div>
<h1>Welcome to my site</h1>
I'm wondering if there is a good way to do this. I'm currently trying to send some temporary data to multiple partial views being called from the same view page in my MVC application.
I'm currently attempting to do this with TempData but I can see my understanding is limited as it is only going through for one partial request. What method do I need to use to filter out to all of my partials?
Main View Page:
#{
ViewBag.Title = "Main View Page";
TempData["ReturnUrl"] = Request.Url.OriginalString.ToString();
}
#Html.Partial("_StatusTable1")
#Html.Partial("_StatusTable2")
#Html.Partial("_StatusTable3")
#Html.Partial("_StatusTable4")
#Html.Partial("_StatusTable5")
Partial View Example:
#{
var temp = TempData["ReturnUrl"]; // temp is null on all partials except the first
}
// Partial View Code ...
Thanks in advance.
In your main view page call the partiel views like that
#Html.Partial("_SomePartial", TempData["ReturnUrl"])
I think that even this would work.
#Html.Partial("_SomePartial", TempData)
Get the value from TempData like this. ReturnUrl Value will retained across all the Partial Views
#{
var temp = TempData.Peek("ReturnUrl");
}
// Partial View Code
Hi I have a partial view setup for handling error messages, but when it's returned it returns a full webpage with just the text No Results Found.
I would expect the Partial View to return inline on my main Index page? As in my Index page I have the code #Html.Partial("_ErrorMessage").
Below is how I'm handling this in my HomeController
else
{
ViewBag.Error = "No results found!";
return PartialView("ErrorMessage");
}
}
Partial view not necessary return html inline. Partial view can return html inline if you call by client script, using jquery, angular, etc.
This way did you make. The return is a whole page.
Context is important here. If you are including the partial view in line in the HTML, you probably don't need to return the partial view in C-sharp unless you're using a fancy asynchronous call to load it.
The in-line partial view should display normally if you just show the view where it was included
I am not sure what the exactly error you are facing but you can try following solution, you have to set Layout as null after you will not facing the full page on your partial view.
#{
Layout = null;
}
If you are not using Layout=null it will call your _Layout page.
Hope it helps you.
I create a helper and i want to get view's path in this helper code, How can i do that?
I try code below. It will use view that return from action. So If i use this helper in partial view it will get parent view name instead.
RazorView view = helper.ViewContext.View as RazorView;
viewPath = view.ViewPath;
Thank you in advance.
You can retrieve the path of the view or partial view using
string path = (helper.ViewDataContainer as WebPageBase).VirtualPath;
This will return something like ~/Views/Home/MyPartial.cshtml
I created some views in visual studio by clicking right click=> add => view.
I select in the selection: "use a layout or master page".
Now I want to turn these views to partial views should I delete it and create new? or I can somehow turning it to partial view without deleting the views?
In Razor there is no much difference in View and partial view
Only difference is
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
If there is no layout specified they could be considered as partial views.
From your controller action you return PartialView(); instead of return View(); this layout will not be applied.