Avoid the View being loaded from the cache - c#

How can I avoid a View being loaded using the cache ?
I tried putting the [OutputCache(Duration = 1)] before my method that returns the View through a ActionResult but without success.
[OutputCache(Duration = 1)]
public ActionResult Receita(string id, string periodo)
{
// Do my stuff
var receita = new ReceitaAssunto()
{
// More stuff
};
return View(receita);
}
When I pass a new value through the method's parameter, should exhibit this values in my View, but it haven't had refresh, always exhibit the old ones.
View
#model Dashboard.Domain.ClasseTipada.ReceitaAssunto
<ul class="list-group clear-list m-t">
#{
var i = 1;
foreach(var elemento in Model.ReceitaPorTipoReceita)
{
<li class="list-group-item fist-item">
<span class="pull-right">
<span id="txtTextoValorLocacao">#elemento.Valor.ToString("C", new System.Globalization.CultureInfo("pt-BR"))</span>
</span>
<span class="label label-success">#i</span>#elemento.DescricaoOrigem
</li>
i++;
}
i = 0;
}
</ul>
UPDATE
I saw the request using Firebug and the result it's exactly what I want, but it doesn't render in my View.
How I saw (take a look at the values), these values it's true only in the first page load
JS
$("#btnTrimestral").on("click", function () {
GeradorGrafico.URLJson = "#Url.Action("Receita", new { periodo = "trimestral" })";
GeradorGrafico.init();
});

put it into Global.asax.cs in Application_BeginRequest().
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();

Related

getting anchor tag href on click from Action Method

I have a grid which includes below hyperlink row,currently for all rows we have same hyperlink and only ID is changing and it is working fine.
<a href=" + #ViewBag.Url+ ID + " target='_blank'>Test</a>
Now for every row, we have different link url which i would get from action method when I pass ID.
I want to call MVC Action Method to get hyperlink url and then open it in another tab.How can I accomplish this?
I tried this one but it is not opening hyperlink?
<div class="row">
<div class="col-md-4">
Click Here;
</div>
</div>
public string GetPDFUrl(string id)
{
return "test.com" + id;
}
There are several ways to solve your problem. one of them is using child actions.
Put your generating URL part into a partial view to put your logic in your action method. So, create a child action method that can only be called in your views.
[ChildActionOnly]
public ActionResult GenerateUrlPartial(int id)
{
var generatedUrl = "";//your url business is here
var model = new UrlInfo { Url = generatedUrl };
return PartialView(model);
}
Then, create GenerateUrlPartial.cshtml partial view :
#model UrlInfo
#{
Layout = null;
ViewBag.Title = "GenerateUrlPartial";
}
<div class="row">
<div class="col-md-4">
Click Here;
</div>
</div>
And in your loop, call the action method like this :
#for (int i = 0; i < 10; i++)
{
Html.RenderAction("GenerateUrlPartial", new { id = i });
}
Hope this helps.

I don't understand why I have null MVC AJAX

I have Get and Post partial Action. Get take me a list of image which I have in ma app.
[HttpGet]
public PartialViewResult ViewImageFileList()
{
IEnumerable<string> allImages = Directory.EnumerateFiles(Server.MapPath("~/Images/NBAlogoImg/"));
return PartialView(allImages);
}
Post delete image which I extra.
[HttpPost]
public PartialViewResult ViewImageFileList(string imageNameType)
{
var fileToDeletePath = Path.Combine(Server.MapPath("~/Images/NBAlogoImg/"), imageNameType);
if (System.IO.File.Exists(fileToDeletePath))
{
fileOperations.Delete(fileToDeletePath);
}
return PartialView();
}
My .chhtml of my partial view
#model IEnumerable<string>
<div class="name-block-style">
Логотипы которые имеются
</div>
<div id=team-logo-wrapper-images>
<ul>
#foreach (var fullPath in Model)
{
var fileName = Path.GetFileName(fullPath);
<li>
<div class="box-name-image">
<p class="image-name-type">#fileName</p>
<img src="#Url.Content(string.Format("~/Images/NBAlogoImg/{0}", fileName))"
class="logo-images" alt="Логотип команды"
title="Логотип команды" />
</div>
</li>
}
</ul>
<div id="delete-image-form" class="form-group">
#using (Ajax.BeginForm(
"ViewImageFileList",
"Team",
new AjaxOptions() { HttpMethod = "POST", OnComplete = "reloadPage()" }))
{
<label>Введите имя с указание типа изображения</label>
<input type="text" class="form-group" name="imageNameType" id="imageNameType" />
<input type="submit" value="Удалить" class="btn btn-primary" />
}
</div>
<script>
function reloadPage() {
location.reload();
}
</script>
My problem is Null references when I write the deleting image and submit it(i do it by ajax). I have this error Null reference but when I click to continue, the image deleted and my script to reload page work.
I want to understand why I take the null and how I can fix it, because it stops my app always when I delete an image.
The problem is that when you POST after you delete the image you don't populate the model of the partial view, as you do correctly in ViewImageFileList. This has a result when the View Engine try to build the view that you would send after the POST to the client, to get a null reference exception when try to perform the foreach on a null reference.
That being said, the thing you need is to pass to the PartialView all the images. So just add before the return statement in the action method you POST this:
var allImages = Directory.EnumerateFiles(Server.MapPath("~/Images/NBAlogoImg/"));
return PatialView(allImages);
When you browsing images you return view with model passed
return PartialView(allImages); //allImages is a model
But when you deleting images you return view without any model
return PartialView(); //need to pass a model
So after deleting you would like to redirect to ViewImageFileList to browse
all images
[HttpPost]
public RedirectToRouteResult ViewImageFileList(string imageNameType)
{
var fileToDeletePath = Path.Combine(Server.MapPath("~/Images/NBAlogoImg/"), imageNameType);
if (System.IO.File.Exists(fileToDeletePath))
{
fileOperations.Delete(fileToDeletePath);
}
return RedirectToAction("ViewImageFileList");
}
or retrieve images in delete action once again and pass the list to view
[HttpPost]
public PartialViewResult ViewImageFileList(string imageNameType)
{
var fileToDeletePath = Path.Combine(Server.MapPath("~/Images/NBAlogoImg/"), imageNameType);
if (System.IO.File.Exists(fileToDeletePath))
{
fileOperations.Delete(fileToDeletePath);
}
IEnumerable<string> allImages = Directory.EnumerateFiles(Server.MapPath("~/Images/NBAlogoImg/"));
return PartialView(allImages);
}

PagedList.MVC - Page buttons(links) don't work as expected

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.

Can PagedList be used to automatically switch pages?

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>

Reloading Partial View with JQuery

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/

Categories

Resources