I have a partial that defines an Ajax.BeginForm. The model returned has a property for ReportLink created on the server resource that returns a Url to a PartialView.
On the Ajax,BeginForm.OnSuccessFunction I am attempting to return and load html content with $("reportContent").load(AJAXRESULT.RenderLink)
However, I get into an infinite loop somewhere.
Edited to add moving parts:
#model xxxx.Reports.Models.Reports.BaseReportModel
#{Layout = null;}
<div id="reportBase" class="k-content">
<div id="reportControl" >
#using (Ajax.BeginForm(
Model.PostAction,
Model.PostController,
null,
new AjaxOptions() { OnSuccess = "editPostSuccess", OnFailure = "editPostFailure" },
new { id = "reportBase_frmViewer", name = "reportBase_frmViewer" }))
{
#Html.AntiForgeryToken()
#RenderSection("reportParams", required: false)
if (#Model.AllowRefresh){
<input type="button" id="btnRefresh" value="refresh" />
}
if (#Model.AllowExportToPDF){
<input type="button" id="btnPDF" value="PDF" />
}
if (#Model.AllowExportToExcel){
<input type="button" id="btnExcel" value="XLS" />
}
#Html.HiddenFor(p => p.AllowExportToExcel)
#Html.HiddenFor(p => p.AllowExportToPDF)
#Html.HiddenFor(p => p.AllowRefresh)
#Html.HiddenFor(p => p.AutoStartReport)
}
</div>
</div>
<div id="wait"></div>
<div id="reportContent"></div>
//The
<script type="text/javascript">
function editPostSuccess(ajaxContext) {
showWaitIndicator(false);
$('#reportContent').load(ajaxContext.RenderLink**,<--This is a link to an asction that calls renderPartial on the controller** function () {
$("#reportContent").show();
});
}
function editPostFailure(ajaxContext) {
showWaitIndicator(false);
var response = JSON.parse(ajaxContext.responseText);
var errorMessage = response.Message;
$('#reportContent').html('#Resources.labels.lblServerErrorsOnForm' + " " + errorMessage);
$("#reportContent").show();
alert("FAILURE:"+response.Message);
}
Update: I am no longer sure that browser is locking up. The content is 3.15 MB. I think the raw html is very verbose and takes that long to render in the browser. Here is the execution sequence:
LoadPartial(ReportModel) - This has an Ajax.BeginForm() that returns report meta data and has a refresh button. When the refresh button is clicked. I call a js function that loads a div using div.load(ReportModel.RenderLink), which is a url to get the content as html from the controller.
The ReportModel.RenderLink points to a controller method that returns an html report based on model params sent to the controller. The result is a PartialView("ReportContentPartial",string) where string is the html fragment.
For testing the ReportContentPartial just dumps #Model into a div as #Html.Raw(Model) and this is where the browser locks up. I thought it was in an infinite loop but it is just taking way to long to render the html.
The part I do not understand is when I use #Html.BeginForm and dump the #Html.Raw(HTML) it is pretty quick. I need to somehow use the same mechanism used in that rendering method. The report html is fetched and returned in less than a second. The problem is when I trace out of #Html.Raw(HTML) the browser locks and takes +15 seconds to render the content.
I will keep plugging at it. I am sure there is a more efficient way to go about it and I probably need to think about ways to break up the reports.
Update 2: This seems to be development environment issue. I am launching IE from VS2012 using the run command. I sense that something is up with the asp.net dev server. When I load the same url in chrome, while debugging in vs, it renders in less than a second.
I solved this. It seems there was an issue with browser definition files that shipped with .net 40. I resorted back to a forms based version of the reporting application that used .aspx pages and postbacks to see why it would render fast and the MVC version was so slow. When using IE 10 it would not render and I found the _dsoPostBacks were not working on the forms version. I then found Scott Hanselman's blog on browsers definition files and applied the hotfix on the test server and now the mvc version in ie is rendering at an acceptable rate. It has something to do with recognizing the browser and downgrading js support. I do not know why that fixed my problem but it did :)
Related
I'm new to working with Razor, and I have a doubt.
I have a page that makes a request to the database to populate a table, but that request takes too long so the HTML waits for the request to be loaded to render in the web browser.
This is the request that takes too long
<section id="studentList" class="form-group">
<div class="table-responsive">
#{Html.RenderAction("Search", new { situation = 3, unity = "", course = "", ra = "", name = "", page = 1 });
}
</div>
</section>
and in my cshtml page and I would like to render de HTML First end then do this request to not be in a blank page waiting to be loaded.
If someone could help me.
I appreciate your attention and I'm really grateful for your help!
A Html.Render(-X) will always be server side constructed, therefor the browser will need to wait before your result is completed because there is no data to transmit. The partial view needs to be completed before anything will be ready to be sent.
Since Razor is still just "MVC" (for nitpicking: yeah I know, it isn't "MVC" I know this, it's a gross simplification, but for lack of a better way to explain this, just accept it "as is"). You can also use (like on a "normal" web page) javascript (or jQuery or whatever framework you want) to load content after document.Ready.
There are multiple ways to achieve this, I suggest you start by searching for "Razor Ajax" or "Razor partial refresh" or whatever.
I'm working with ASP.NET Core Razor pages and an Oracle database. The team has decided to go without Entity Framework and now I am at the point of loading data from the database using ODP.net (Oracle's version of ADO.NET).
I know with Entity Framework, I could take advantage of asynchronous programming but since I am not, loading the page is slow (since I query all the tabs at once). I am using Bootstraps nav tabs.
Everything works fine but now the data set is getting bigger because there are over ten tabs that load on page load. Is there a way to only load each tab on click? Are there other ways to go about this?
Not sure if I understand your question entirely. But how I read this question is you have to load your page whenever a tab changes and don't want to load the entire page at once at the beginning. This has nothing to do with which ORM you use at the backend as I see it. What need to make a asynchronous javascript call to the server when user clicks on the tab and load a partial page under that tab.
https://getbootstrap.com/docs/4.0/components/navs/
show.bs.tab (on the to-be-shown tab)
shown.bs.tab (on the newly-active just-shown tab, the same one as for the show.bs.tab event)
I suggest you use the first event and in that event make an ajax call to a partial page.
https://www.learnrazorpages.com/razor-pages/ajax/partial-update
#page
#model RazorPagesTests.Pages.AjaxPartialModel
<h2>Ajax</h2>
<p><button class="btn btn-primary" id="load">Load</button></p>
<div id="grid"></div>
#section scripts{
<script>
document.getElementById('load').addEventListener('click', () => {
fetch('/ajaxpartial?handler=CarPartial')
.then((response) => {
return response.text();
})
.then((result) => {
document.getElementById('grid').innerHTML = result;
});
});
</script>
}
Hope it helps. If not then I'm here to help you. Please give me more information what you want to do.
I am working on an asp.net core application where I am loading a view on click of a hyperlink. The view loads fine but what strange thing happening here is whenever I click on the hyperlink, call to controller's action goes twice. I accidently found this issue when I put debug point on the action method and it got hit twice. Then I also checked the network traffic tab in the browser, there also I noticed 2 calls to controller action got recorded twice.
Markup of hyperlink in layout page:
<li><a asp-action="ApplyLeave" asp-controller="Home">Apply Leave</a></li>
Controller's action method:
[HttpGet]
public IActionResult ApplyLeave()
{
.......
.......
.......
return View();
}
ApplyLeave.cshtml
#{
ViewData["Title"] = "Apply Leave";
}
<header class="page-header">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h2 class="no-margin-bottom">
Apply Leave
</h2>
</div>
</div>
</div>
</header>
Screenshot of network traffic captured in browser:
Kindly help me in resolving this issue, thanks in advance!
If you see your request in console window on network tab, there is two kind of request:-
1: Doc Type
2: XmlHttpRequest
Doc type request is coming from the View which is action link where action method name is mention, but if you see another request then, this request comes from Javascript environment.
Please see the official definition of XMLHttpRequest:-
XMLHttpRequest (XHR) is an API in the form of an object whose methods transfer data between a web browser and a web server. The object is provided by the browser's JavaScript environment.
Please validate once your JS part.
Thanks you all for your kind attention on this.
I have site.js where I am keeping all the script code and code for ajax calls.
There was an ajax call which was intended to be called on a particular page, but due to improper code, that ajax call was triggering after every other page load.
So I corrected the code for that ajax call and now I am not seeing any duplicate call to controller, everything is working fine.
Thanks everyone.
I want to add a PartialView multiple times by pressing a button.
<div id="FilterRows">
#{Html.RenderAction("_FilterRow");}
</div>
<button id="newRow" type="button"
class="btn btn-sm btn-default"
style="width: 50px">+</button>
This piece of code works properly. But now i want to append the div FilterRows with another PartialView of _FilterRow at clicking on the button.
This is how it looks today:
Something like:
$(document).ready(function() {
$("#newRow").click(function() {
$("#Exec").append("<br>", #{Html.RenderAction("_FilterRow");} {
});
});
});
Is unfortunately not working. Any Ideas?
If you add an action which returns the partial rendered as a partial (ie. return PartialView("myView", model); then you can load using jQuery:
# Create a new element to contain...
var el = $('<div></div>');
$('#parent').append(el);
# ...the new content
el.load('#Url.Action("action", "controller"');
(This means running the JS in the razor view to get the correct URL generation. If most of the JS is in its own file, pass the URL from a little JS in the Razor file just for things like URLs.)
As long as your script is in the page (and not in an external .js file) you can use Razor inside js (although feedback directly from MicroSoft indicates that this is "unexpected", it works fine).
Have a look at the rendered html to see what's wrong.
In this case you need quotes (") around the render action:
$("#FilterRows").append("#{Html.RenderAction("_FilterRow");}");
This assumes a number of potential issues:
the 'RenderAction' can't have any newlines in the output
the 'RenderAction' can't have any quotes in the output (either use ' on the append and " inside the render or the other-way-around)
the action to be rendered cannot have any row-specific parameters (which appears to be ok in this case to add a new blank row)
the script must be in a .cshtml file (though you can get around this by setting a global/namespace'd variable in the .cshtml and have the actual code in a .js file)
you need to use the correct combination of #{}/#() and render/tostring
You might be better off with #Html.RenderPartial if you just want to render some html and don't need an action.
An alternative, perhaps more friendly, mechanism would be to have the blank-row already on the page (perhaps hidden) and use .clone().
I have an application that takes some user input from a view, the reports the user wants, and creates a parameter string from it in the controller, and I need to open up multiple report urls after the query string is created but not sure how:
View snippet:
#Html.EditorFor(model => model.Id)
#Html.CheckBoxFor(model => model.report1) Report1
#Html.CheckBoxFor(model => model.report2) Report2
#Html.CheckBoxFor(model => model.report3) Report3
<input type="submit" value="Index" />
controller snippet
[HttpPost]
public ActionResult Index(ViewModel model) {
string parameters="&id="+model";
if(model.report1==true)
{
string report1="http://<urlhere>"+parameters;
}
//CONTINUE for the other two reports as well
}
I need to open the reports in multiple tabs. I have researched it extensively and it seems like you can't open multiple tabs from the controller, so I'm at a loss. I considered putting the urls in a list, passing them into a View, and using JavaScript to open them on the page load, but I honestly am not sure how to do that in Javascript and MVC.
As you already found out this is not possible from the server side, so pass the report URLs to the client and use something like the following JavaScript:
#if (!String.IsNullOrWhiteSpace(Model.ReportUri))
{
<a id="reportLink" href="#Model.ReportUri" target="_blank">REPORT</a>
<script type="text/javascript">
var link = document.getElementById('reportLink');
link.click();
link.parentNode.removeChild(link);
</script>
}
Please keep in mind, that popup-blockers will most likely block this, so you should tell this somehow to the user. Also maybe it is usefull to keep the links on the page in your case (so remove the last line of my script) to give the user the chance to manually open them when they get blocked...