I just trying to change my usercontrol function to razor function.but the page load time by using razor function is more than usercontrol function can any one know why this time taken.here is my razor code
#inherits RazorFunction
#using System.Linq;
#using Composite.Data;
#using Atc.Data;
#using System.Web.UI.WebControls;
#using System.Collections.Generic;
#functions {
public override string FunctionDescription
{
get { return "Function for footer"; }
}
}
<ul>
<li>##Copyright 2012 </li>
#{
using(DataConnection dCon =new DataConnection())
{
SitemapNavigator sn = new SitemapNavigator(dCon);
PageNode p = sn.CurrentHomePageNode;
List<PageNode> hiddenPages = dCon.Get<Page_Settings>()
.Where(x => x.FooterNavVisibility == true).OrderBy(x => x.Position)
.Select(x => sn.GetPageNodeById(x.PageId))
.ToList<PageNode>();
foreach (var item in hiddenPages)
{
<li>#item.Title</li>
}
}
}
<li>
<!-- AddThis Button BEGIN -->
<div class="addthis_toolbox addthis_default_style ">
<a class="addthis_button_compact"></a>
<a class="addthis_counter addthis_bubble_style"></a>
</div>
</li>
</ul>
<script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#pubid=ra-5008fecf0e8dcc29"></script>
It could be that actual UserControl's execution time was accounted in the line "ASP.NET controls: PageLoad, EventHandling, PreRender", which currently takes 91 ms.
On a side note: now need to create new DataConnection/SitemapNavigator objects -> there are Data, and SitemapNavigator properties on the base class for the razor functions.
If you want to optimize it, you can f.e. cache the "hiddenPages" variable, and clear cache on Page or PageSettings data type changes.
Related
I've got a navbar at the top of my ASP.Net CORE site and I'm trying to create dynamic menu options. So far, I'm just trying to replace some of the options on the _layout page with a ViewComponent like I've done in a few other projects.
<header>
<nav class="navTop">
<a class="logo" asp-controller="Home" asp-action="Index">
<img src="~/Images/logo.svg" />
</a>
#{ await Component.InvokeAsync("MainMenu"); }
#{ await Html.RenderPartialAsync("_LoginPartial"); }
</nav>
</header>
I have my Component View in the folder
Views > Shared > Components > MainMenu > Default.cshtml
Which looks like this:
#model IEnumerable<MyProject.Models.Home.MainMenuItem>
#foreach (var item in Model)
{
#Html.ActionLink(item.DisplayText, item.Action, item.Controller)
}
And the ViewComponent InvokeAsync looks like:
public async Task<IViewComponentResult> InvokeAsync()
{
var x = new DataAccess.Menus.Menu(_context).GetMainMenuItems(User.Identity.Name);
return View(x);
}
And the DataAccess method is simply returning a List of MyProject.Models.Home.MainMenuItem as expected, which has everything populated fine when I step through, but nothing is resulting on the page in the in place of #{ await Component.InvokeAsync("MainMenu"); }!
I've done this before in a few other projects and never had a problem - so I don't know why this could be going wrong. Any ideas?!
It's getting to the view and I can even see it stepping through the foreach loop with the correct populated properties so why does nothing show up on the page?
You should write it like this
#{ #await Component.InvokeAsync("MainMenu") }
Or directly
#await Component.InvokeAsync("MainMenu")
This is a question related to this post (which is also made by me)
All the explanation of the website I'm creating is in the link above. Please see it there.
That being said, I'm trying to have two models of different types within a razor, and I'm having difficulty properly dealing with the directives, (#using #inherits, and all that)
and I get errors saying it failed to bind my custom made model to the one that is created by the CMS (UmbracoTemplateView).
In the course of thinking how to circumvent this, I came up with assigning #using directive for IPublishedContent, thus something like below.
This way, the UmbracoTemplateView should be assigned to a variable with a much narrower scope, meaningI should be able to avoid triggering that error.
#model CodeShare.Library.Models.SearchViewModel
#using CodeShare.Web.Controllers
<div class="carousel-inner">
<div class="carousel-item active">
<!--this part uses UmbracoTemplatePage to render the content dynamically-->
#using (UmbracoTemplatePage)
{
var pageSize = 5;
IEnumerable<IPublishedContent> newsPosts = Umbraco.AssignedContentItem.DescendantOrSelf("news").Children.Where(x => x.IsVisible() && x.DocumentTypeAlias == "newsPost").OrderByDescending(x => x.UpdateDate);
var page = 1; int.TryParse(Request.QueryString["p"], out page);
var totalPages = (int)Math.Ceiling((double)newsPosts.Count() / (double)pageSize);
if (page > totalPages)
{
page = totalPages;
}
else if (page < 1)
{
page = 1;
}
}
#foreach (var item in newsPosts.Skip((page - 1) * pageSize).Take(pageSize))
{
var imagid = item.GetPropertyValue("image");
string imgurl = Umbraco.Media(imagid.ToString()).Url;
<a href="#item.Url" class="media">
<img src="#imgurl">
<div class="media-body">
<h5 class="mt-0">#item.Name</h5>
<span>最終更新日: #item.UpdateDate.ToString("yyyy/MM/dd") </span>
</div>
</a>
}
</div>
From here I want to use the custom model, because the input will made by the user not in the backoffice.
in my understanding, with this beginform method below, it sends those HiddenFor's as a set of parameters to the method called "SubmitSearchForm" in a controller class called "SurfaceController"
#using (Ajax.BeginForm("SubmitSearchForm", "Surface", new AjaxOptions()
{
UpdateTargetId = "carousel",
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
}))
#Html.HiddenFor(m => m.DocTypeAliases)
#Html.HiddenFor(m => m.FieldPropertyAliases)
#Html.HiddenFor(m => m.PageSize)
#Html.HiddenFor(m => m.PagingGroupSize)
#Html.TextBoxFor(m => m.SearchTerm)
}
<button id="submit-button">Search</button>
<div class="carousel">
#{ Html.RenderAction("RenderSearchResults", "Surface", new { Model = Model.SearchResults });}
</div>
}
The only change from the one I posted on our.umbraco is #using directive when trying to render from the model, which is of "UmbracoTemplateView".
Here, I'm receiving an error saying the directive that can be assigned to the #using directive here must be of the type "IDisposable" and UmbracoTemplateView is not.
I understand what is meant by the error:
UmbracoTemplateView is not a native type from .NET thus needs to be clearly specified when it can be disposed of to signal at the garbage collector. How can I assign this interface?
========================================================================
added on 18/10/2018
I separated these two views in different cshtml's but I'm having the same problem at a higher level (should I call this node)
So when I display the page, it will be delegated like
"WebBase.cshtml"=>"Home.cshtml" => "Parts that need UmbracoTemplateView(in cshtml)" & "Parts that need custom model(in cshtml)" ....
//I get an error when I put the following two in the same cshtml
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#model CodeShare.Library.Models.SearchViewModel
#using CodeShare.Web.Controllers
#using ClientDependency.Core.Mvc
#{
Layout = "WebBase.cshtml";
}
#* the fun starts here *#
#{Html.RenderPartial("~/Views/Partials/Home/.....cshtml");}
#{Html.RenderPartial("~/Views/Partials/Home/....cshtml");}
#{Html.RenderPartial("~/Views/Partials/Home/.....cshtml");}
<!-- only this "news" part requires custom model by Mr.Paul -->
#{Html.RenderPartial("~/Views/Partials/Home/_News.cshtml");}
#{Html.RenderPartial("~/Views/Partials/Home/....cshtml");}
As such at some point I am going to need two models of different types in one place anyway
I wanted to implement a simple pagination, and PagedList.MVC NuGet package sounded like the best solution for me. HOWEVER, when I click on generated buttons to go to 2nd, 3rd, etc. page, 1st one remains active, and all that happens is refresh of the first page, but I obviously want it to navigate to the expected page...
I followed these two tutorials to see if I've done everything right:
Github
Microsoft
My controller:
public ActionResult Index(int? pageNumber)
{
var modelList = _employeeService.GetEmployeeViewToPagedList(pageNumber);
return View(modelList);
}
The service method that gets called (I know that "ToPagedList()" is usually called from the controller, but the current state is a result of trying everything, and the fact that I get "DbContext disposed" error if I modify to return something like "View(modelList.ToPagedList(pageNumber, pageSize))" from the controller):
public IPagedList<EmployeeView> GetEmployeeViewToPagedList(int? pageNumber)
{
using (var _unitOfWork = UnitOfWork.GetUnitOfWork())
{
var list = (IQueryable<EmployeeView>)_unitOfWork.context.EmployeeViews.OrderByDescending(x => x.Id);
return list.ToPagedList((pageNumber ?? 1), 10);
}
}
My view:
#model PagedList.IPagedList<Company.DAL.Views.EmployeeView>
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Index";
}
<h2>List of all employees</h2>
<p>
#Html.ActionLink("Add new employee", "AddNewEmployee")
</p>
#if (Model != null && Model.Count() > 0)
{
<table class="table">
... all needed <tr>'s, <th>'s, <td>'s ...
</table>
<br/>
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, pageSize =
Model.PageSize }))
}
I am trying to figure this out for days now, and the closest I got was this question, but I am not sure where to find that JS function, so I could try that as well.
EDIT:
Generated HTML:
<div class="pagination-container">
<ul class="pagination">
<li class="active"><a>1</a></li>
<li>2</li>
<li>3</li>
<li class="PagedList-skipToNext">»</li>
</ul>
</div>
I decided to post an answer here, since I solved the problem, and somebody else might find this useful.
So, in the controller, my Index method looks like this:
public ActionResult Index(int? pageNumber)
{
//some logic
}
As you can see, it accepts an int variable named pageNumber as a parameter.
But then there's this on my view:
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, pageSize = Model.PageSize }))
SO, here I am passing a variable named page to my Index method.
That's the mistake! Variable in the method parameter list has to be named page as well.
I am using asp.net-mvc and I have a PageList from https://github.com/TroyGoode/PagedList in my project, it works fine but I would like to be able to switch the pages automatically on a set time interval. The pages I am using have a set number of accordion items and wanted to know how I could switch the page number without human interaction. Like use a slideshow with pagedList. Is there something better to use or is this possible?
My Index.cshtml
#model PagedList.IPagedList<ComputerDownTimeTracker.Models.DashboardTicketListVM>
#using PagedList.Mvc;
<body>
<div class="list1">
<div id="accordion">
#foreach (var item in Model)
{
<div class="header">
<b> Equipment: </b>#item.ComputerName <br />
<b> Location: </b>#item.Location
#switch (item.RunningStatus)
{
case 1: imagePath = down;
break;
case 2: imagePath = running;
break;
case 3: imagePath = waiting;
break;
case 4: imagePath = waiting;
break;
default: imagePath = running;
break;
}
<img class="status" src="#imagePath" alt="" />
<ul class="timeStat">
<li><b class="time">Computer Down At :</b> #item.OnClickTimeStamp</li>
#if (#item.RunningStatus == 4)
{
<li> <b class="time"> Maintenance On issue :</b> #item.EditTimeStamp</li>
}
#if (#item.RunningStatus == 3)
{
<li> <b class="time">Waiting For Parts :</b> #item.EditTimeStamp</li>
}
#if (#item.RunningStatus == 2)
{
<li> <b class="time">Computer Restarted :</b> #item.EditTimeStamp</li>
}
</ul>
</div>#*//computer name and status div*#
<div><p>#Html.Raw(#item.ComputerStatus)</p></div>
}
#(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index",new { page }))
</div>
</div>
My Home controller index method
public ActionResult Index(int? page)
{
var time = DateTime.Now;
time = time.AddSeconds(-100);
var ViewModel = _ComputerDB.Database.SqlQuery<DashboardTicketListVM>(listQuery).ToList();
var remove_running = ViewModel.Where(x => x.OnRestartTimeStamp >= time || x.OnRestartTimeStamp == null);
int pageSize = 8;
int pageNumber = (page ?? 1);
return View("Index", "~/Views/Shared/_ListLayout.cshtml", remove_running.ToPagedList(pageNumber, pageSize));
}
I omitted a lot of stuff that wasn't really relevant
You need use use Javascript setTimeout to reload the next page after some specified time.
Using the PagedList examples:
Controller
public class ProductController : Controller
{
public object Index(int? page)
{
var products = MyProductDataSource.FindAllProducts(); //returns IQueryable<Product> representing an unknown number of products. a thousand maybe?
var pageNumber = page ?? 1; // if no page was specified in the querystring, default to the first page (1)
var onePageOfProducts = products.ToPagedList(pageNumber, 25); // will only contain 25 products max because of the pageSize
ViewBag.OnePageOfProducts = onePageOfProducts;
return View();
}
}
View
#{
ViewBag.Title = "Product Listing"
}
#using PagedList.Mvc; //import this so we get our HTML Helper
#using PagedList; //import this so we can cast our list to IPagedList (only necessary because ViewBag is dynamic)
<!-- import the included stylesheet for some (very basic) default styling -->
<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />
<!-- loop through each of your products and display it however you want. we're just printing the name here -->
<h2>List of Products</h2>
<ul>
#foreach(var product in ViewBag.OnePageOfProducts){
<li>#product.Name</li>
}
</ul>
<!-- output a paging control that lets the user navigation to the previous page, next page, etc -->
#Html.PagedListPager( (IPagedList)ViewBag.OnePageOfProducts, page => Url.Action("Index", new { page }) )
View Javascript
<script type="text/javascript">
var nextPage = #(((IPagedList)ViewBag.OnePageOfProducts.PageNumber) + 1); // next page number is current page number + 1
setTimeout(function() {
window.location = "index?page=" + nextPage; // load new page after timeout
}, (5 * 1000) /* set timeout here, example: 5 seconds */);
</script>
Note: You may need to add some additional logic to make sure to stop the next page loading whenever you get to the end of your pages. You can do this by checked the HasNextPage property provided by PagedList.
Example:
<script type="text/javascript">
var hasNextPage = #(((IPagedList)ViewBag.OnePageOfProducts.HasNextPage) ? "true" : "false");
if(hasNextPage) {
var nextPage = #(((IPagedList)ViewBag.OnePageOfProducts.PageNumber) + 1); // next page number is current page number + 1
setTimeout(function() {
window.location = "index?page=" + nextPage; // load new page after timeout
}, (5 * 1000) /* set timeout here, example: 5 seconds */);
}
</script>
I have a page with a video at the top and a list of videos you can choose from. Currently, clicking a link in the video list will reload the entire page. I need it to only refresh the partial view I have containing the video at the top of the page.
I saw several posts here on SO showing how to reload partial views with JQuery, but couldn't get it to work correctly in my situation. I'm unsure how to pass the correct id of the video along.
Controller:
public ActionResult Videos(int topVideo = 0)
{
VideosModel model = new VideosModel();
model.Videos = StatsVideoService.GetEntityList(new Lookup(TableStatsVideo.IsDeleted, false)).OrderByDescending(x => x.DateCreated).ToList();
if (topVideo == 0)
model.TopVideo = model.Videos.First();
else
{
model.TopVideo = model.Videos.Where(x => x.StatsVideoId == topVideo).FirstOrDefault();
if (model.TopVideo == null)
model.TopVideo = model.Videos.First();
}
return View(model);
}
View:
#model Project.Models.VideosModel
<section class="videos">
<div id="top_video">
#{Html.RenderPartial("StatsVideo", Model.TopVideo);}
</div>
<ul>
#foreach (var item in Model.Videos)
{
<li>
<div class="videoList">
<a href ="#Url.Action("Videos", "Home", new { topVideo = item.StatsVideoId })">
<img src="#Url.Content("~/Content/img/video-ph.png")" />
</a>
<p class="videoTitle">#item.Title</p>
</div>
</li>
}
</ul>
</section>
If there's any more information needed, please let me know.
After several hours of bashing my head against the wall, I got it to work! Just as a reference to anyone else in the future who's viewing this article, here's how I got it to work:
I set the onclick of the link to point to a javascript method, passing in the id of the video as a parameter:
#foreach (var item in Model.Videos)
{
<li>
<div class="videoList">
<a href ="#" onclick="updateTopVideo(#item.StatsVideoId)">
<img src="#Url.Content("~/Content/img/video-ph.png")" />
</a>
<p class="videoTitle">#item.Title</p>
</div>
</li>
}
And then I included this script in the view at the bottom:
<script>
var updateTopVideo = function (itemId) {
var url = '#Url.Content("~/Home/StatsVideo/")';
url = url + itemId;
$.get(url, "", callBack, "html");
};
var callBack = function (response) {
$('#top_video').html(response);
};
</script>
Finally, I added a method to my controller that would return the partial view needed for the video at the top of the screen:
public ActionResult StatsVideo(int Id)
{
IStatsVideo vid = StatsVideoService.GetEntity(new Lookup(TableStatsVideo.StatsVideoId, Id));
if (vid == null)
vid = StatsVideoService.GetEntityList(new Lookup(TableStatsVideo.IsDeleted, false)).OrderByDescending(x => x.DateCreated).FirstOrDefault();
return PartialView(vid);
}
This code should be fairly easy to understand. Basically, the onclick calls the first javascript method, which then calls the controller. The controller builds the partial view and returns it. The first javascript method passes it to the second javascript method which sets the html of the div "top_video" to be the returned partial view.
If anything doesn't make sense, or anyone's having trouble with this in the future, let me know and I'll do my best to offer some help.
I think there may be several confusing and inconsistent elements here.
First, you are returning a full view instead of a partial view. This reloads all containing elements, not just the part that is relevant to your partial view.
Second, you are using Url.Action, which only generates the url. I would recommend using Ajax.ActionLink, which allows you to do fully ajax calls, refreshing the content of your partial div and updating a target div element.
instead of:
<div class="videoList">
<a href ="#Url.Action("Videos", "Home", new { topVideo = item.StatsVideoId })">
<img src="#Url.Content("~/Content/img/video-ph.png")" />
</a>
<p class="videoTitle">#item.Title</p>
</div>
try the more modern solution
<div class="videoList">
#Ajax.ActionLink(
"Videos",
"Home",
"new { topVideo = item.StatsVideoId },
new AjaxOptions {
HttpMethod = "GET",
OnSuccess = "handleSuccess"
}
)
</div>
This way you can be very specific on what you want each link to do, and you can pass along multiple parameters as well as define a callback function. You can also use "UpdateTargetId" in your ajax options to load your newly refreshed partial view into a DOM element.
You can remove the around the image and just store the url generated by the Url.Action in a data-href attribute.
Then you can use the jquery load method to load the data:
$(".videolist>img").click(function () {
$("#content").load($(this).data("href"));
});
I created a fiddle that loads content dynamically here, so you can play with it if you want: http://jsfiddle.net/bTsLV/1/