Reload page after file download via Response - asp.net

I'm writing a reporting tool in which you can display a report straight to the page or download it as an excel file. In case you just want to show it on the page the site reloads as expected. in case it is downloaded as excel file the download works but the page is not reloaded. Thats a problem for me because I have no clue how to disable the loading animation afterwards. The download is accomplished with a write action to the response object. Here is the code:
private void ExcelExport(DataTable outList)
{
ViewBag.Reload = true;
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=report.xls");
Response.ContentType = "application/ms-excel";
Response.Charset = "";
Response.Output.Write(Excel.GetXml(outList));
Response.Flush();
Response.End();
}
The code is called from an ActionResult method within my controller (where the ExcelExport Method is also located):
public ActionResult WisPriceMatrix(string cc, string sl, string exp)
{
ViewBag.StorageLocations = this.StorageLocations;
ViewBag.WisPriceMatrixReport = null;
int cleanCode = 3;
if ((cc != null && cc != string.Empty && Int32.TryParse(cc, out cleanCode)) || (sl != null && sl != string.Empty))
{
sl = sl == string.Empty ? null : sl;
ViewBag.ParameterSl = sl;
ViewBag.ParameterCleanCode = cleanCode;
DataTable outList = dc.GetWisPriceMatrix(sl, cleanCode);
if (exp == null || exp == string.Empty || exp != "1")
{
ViewBag.WisPriceMatrixReport = outList;
}
else
{
if (outList.Count > 0)
{
this.ExcelExport(outList);
}
else
{
ViewBag.NoResults = "1";
}
}
}
return View();
}
Any Ideas how I could force the page to reload afterwards?
I tried to create a ViewBag variable that would indicate that a reload is neede and react to it via JavaScript but since the page isn't refreshed this is of nu success ;-).

In your case in order to reload page either you can use Viewbag and set Viewbag value on Controller say Viewbag.data="reload" and then on view check Viewbag as
$(document).ready(function(){
if('#Viewbag.data' == "reload")
{
window.location.reload(true);
}
});
OR you can just instead of return View() use return RedirectToAction("WisPriceMatrix") as RedirectToAction create a new http(302) request and reloads the page.

Related

ASP.NET Core 5.0 MVC - generate pop up message in controller

I don't really have an idea how to handle it.
Idea is simple: user presses next page button, but returned data is empty, which means previous page was the last one. User is redirected to current page (last one with data) so they won't go too far, but I want to inform them why they can't go further.
[HttpGet]
public IActionResult Index(int page = 1)
{
var data = new List<DataModel>();
page = page < 1 ? 1 : page;
ViewBag.CurrentPage = page;
try
{
var data = ...get data...
if (data.Count == 0 && page > 1)
{
//declare pop up message
return RedirectToAction("Index", new { page = page - 1 });
}
}
catch (TimeoutException)
{
return RedirectToAction("Index", "Error");
}
return View(data);
}
I tried some googling but it looks like troublesome task, and even if it works in one browser, it won't work in the other. I don't expect that you will do this for me, but I would like some guidance which solution is optimal.
One approach would be to define a custom parameter in your Index method:
[HttpGet]
public IActionResult Index(int page = 1, bool isLastPage = false) {
/* ... */
}
Now by default this is false. Now you can check, whether it is true and set your ViewModel or ViewBag/Data flag accordingly:
[HttpGet]
public IActionResult Index(int page = 1)
{
var data = new List<DataModel>();
page = page < 1 ? 1 : page;
ViewBag.CurrentPage = page;
//pass flag to view here
ViewBag.IsLastPage = isLastPage;
try
{
var data = ...get data...
if (data.Count == 0 && page > 1)
{
//declare pop up message
return RedirectToAction("Index", new { page = page - 1, isLastPage = true });
}
}
catch (TimeoutException)
{
return RedirectToAction("Index", "Error");
}
return View(data);
}
In your RedirectToAction call you set your flag to true, so in the redirect it will be triggered.

Inspite of checking for null with usercontrol checkboxlist is returning object reference not set to an instance of an object

I have a group of 7 checkboxes in checkboxlist user control. I build a string in the selectedIndexchanged event for the boxes checked, pass to ViewState and then pass ViewState to the Property. I do this because in the instance when no checkboxes are selected I want to handle null. The problem is no matter how I check for null, the system is throwing object reference error. This current setup works fine if at least one checkbox is checked but if none are checked it fails. How do I check for null? Should I be checking for null in the property or the host aspx page?
I have researched difference ways to do this and I have tried many. My thought is using IsNullOrEmpty or IsNullOrWhiteSpace would be the correct way to go but neither are working.
User Control class - global variable
private string _daysOffInputString = string.Empty;
User Control Property
public string DaysOffSelectedValues
{
get
{
if (string.IsNullOrEmpty(ViewState["DaysOff"].ToString()))
{
_daysOffInputString = string.Empty;
}
else
{
_daysOffInputString = ViewState["DaysOff"].ToString();
}
return _daysOffInputString;
}
set { _daysOffInputString = value; }
User Control event
protected void CbDaysOff_SelectedIndexChanged(object sender, EventArgs e)
{
CheckBoxList chkbx = (CheckBoxList)sender;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chkbx.Items.Count; i++)
{
if (chkbx.Items[i].Selected)
{
sb.Append(chkbx.Items[i].Text + ", ");
}
if (!String.IsNullOrEmpty(sb.ToString()))
{
//Remove last comma & space from string
_daysOffInputString = sb.ToString().Substring(0, sb.ToString().Length - 2);
}
else
{
_daysOffInputString = string.Empty;
}
}
ViewState["DaysOff"] = _daysOffInputString;
}
aspx page - snippet where I retrieve uc property value:
case 2:
blnFlag = false;
ucDaysOff uc3 = row.Cells[3].FindControl("ucDaysOff3") as ucDaysOff;
strAnswer = uc3.DaysOffSelectedValues; //e.g. "Sat, Sun"
break;
SOLUTION: In the user control property DaysOffSelectedValues I was casting ViewState["DaysOff"] to string before checking for null which was the problem. Here's the code that works:
public string DaysOffSelectedValues
{
get
{
if (ViewState["DaysOff"] == null)
{
//_daysOffInputString = string.Empty; }
_daysOffInputString = "Nothing to see here.";
}
else
{
_daysOffInputString = ViewState["DaysOff"].ToString();
}
return _daysOffInputString;
}
set { _daysOffInputString = value; }
}
You should always check if the object, in this case ViewState, is null before using it. Lets say ViewState["DaysOff"] has not been created or has been removed.
Then this will throw a nullreference:
string str = String.IsNullOrEmpty(ViewState["DaysOff"].ToString());
Because you are not checking the ViewState object for null, but the string it is supposed to hold.
So do this
if (ViewState["DaysOff"] != null)
{
string str = ViewState["DaysOff"].ToString();
}

A simple secenario to implement JavaScript ASP.NET C#, question rephrased

I had asked this question before, but I got no correct answer.
So, this is a simple thing:
textbox.text='user typing';
Button: store the value to a variable and a database.
Very simple, nothing to it.
But there should be no post back, that is the page must not load again.
Try Ajax? I tried it, but it is not working.
I lost a lot of time trying to implement this using JavaScript Ajax and read many many posts.
But for some reason I cannot implement the functionality correctly.
var xmlHttp;
var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5")!=-1) ? 1 : 0;
var is_opera = ((navigator.userAgent.indexOf("Opera6")!=-1)||(navigator.userAgent.indexOf("Opera/6")!=-1)) ? 1 : 0;
//netscape, safari, mozilla behave the same???
var is_netscape = (navigator.userAgent.indexOf('Netscape') >= 0) ? 1 : 0;
function btnClick(){
if (strReportURL.length > 0)
{
//Create the xmlHttp object to use in the request
//stateChangeHandler will fire when the state has changed, i.e. data is received back
// This is non-blocking (asynchronous)
xmlHttp = GetXmlHttpObject(handler);
//Send the xmlHttp get to the specified url
xmlHttp_Get(xmlHttp, "AjaxHanlder.aspx?Data="+txtData.Text,handler);
}
}
//stateChangeHandler will fire when the state has changed, i.e. data is received back
// This is non-blocking (asynchronous)
function handler()
{
//readyState of 4 or 'complete' represents that data has been returned
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 'complete')
{
//Gather the results from the callback
var result = xmlHttp.responseText;
//Populate the innerHTML of the div with the results
document.getElementById('lblResult').innerHTML = result;
}
}
// XMLHttp send GET request
function xmlHttp_Get(xmlhttp, url,handler) {
xmlhttp.open('GET', url, true);
xmlhttp.onreadystatechange = handler;
xmlhttp.send(null);
}
function GetXmlHttpObject(handler) {
var objXmlHttp = null; //Holds the local xmlHTTP object instance
//Depending on the browser, try to create the xmlHttp object
if (is_ie){
//The object to create depends on version of IE
//If it isn't ie5, then default to the Msxml2.XMLHTTP object
var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';
//Attempt to create the object
try{
if(!objXmlHttp)
objXmlHttp = new ActiveXObject(strObjName);
//objXmlHttp.onreadystatechange = handler;
}
catch(e){
//Object creation errored
alert('IE detected, but object could not be created. Verify that active scripting and activeX controls are enabled');
return;
}
}
else if (is_opera){
//Opera has some issues with xmlHttp object functionality
alert('Opera detected. The page may not behave as expected.');
return;
}
else{
// Mozilla | Netscape | Safari
objXmlHttp = new XMLHttpRequest();
objXmlHttp.onload = handler;
objXmlHttp.onerror = handler;
}
//Return the instantiated object
return objXmlHttp;
}
///AJAX HANDLER PAGE
public class AjaxHandler : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
if(Request.QueryString["Data"]!=null)
{
StoreYourData(Request.QueryString);
}
}
}

Auto save of form

I have form in ASP.NET 3.5. Where lot of data elements and where i have Save and Submit buttions. I need to auto save my form every 2 min. What is the best way to implement this kind of functionility in ASP.NET.
I struggled for awhile with the same problem. The trouble was that I didn't want to save into the usual database tables because that would've required validation (validating integers, currencies, dates, etc). And I didn't want to nag the user about that when they may be trying to leave.
What I finally came up with was a table called AjaxSavedData and making Ajax calls to populate it. AjaxSavedData is a permanent table in the database, but the data it contains tends to be temporary. In other words, it'll store the user's data temporarily until they actually complete the page and move onto the next one.
The table is composed of just a few columns:
AjaxSavedDataID - int:
Primary key.
UserID - int:
Identify the user (easy enough).
PageName - varchar(100):
Necessary if you're working with multiple pages.
ControlID - varchar(100):
I call this a ControlID, but it's really just the ClientID property that .NET exposes for all of the WebControls. So if for example txtEmail was inside a user control named Contact then the ClientID would be Contact_txtEmail.
Value - varchar(MAX):
The value the user entered for a given field or control.
DateChanged - datetime:
The date the value was added or modified.
Along with some custom controls, this system makes it easy for all of this to "just work." On our site, the ClientID of each textbox, dropdownlist, radiobuttonlist, etc is guaranteed to be unique and consistent for a given page. So I was able to write all of this so that the retrieval of the saved data works automatically. In other words, I don't have to wire-up this functionality every time I add some fields to a form.
This auto-saving functionality will be making its way into a very dynamic online business insurance application at techinsurance.com to make it a little more user friendly.
In case you're interested, here's the Javascript that allows auto-saving:
function getNewHTTPObject() {
var xmlhttp;
/** Special IE only code */
/*#cc_on
#if (#_jscript_version >= 5)
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E) {
xmlhttp = false;
}
}
#else
xmlhttp = false;
#end
#*/
/** Every other browser on the planet */
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
try {
xmlhttp = new XMLHttpRequest();
}
catch (e) {
xmlhttp = false;
}
}
return xmlhttp;
}
function AjaxSend(url, myfunction) {
var xmlHttp = getNewHTTPObject();
url = url + "&_did=" + Date();
xmlHttp.open("GET", url, true);
var requestTimer = setTimeout(function() { xmlHttp.abort(); }, 2000);
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2005 00:00:00 GMT");
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState != 4)
return;
var result = xmlHttp.responseText;
myfunction(result);
};
xmlHttp.send(null);
}
// Autosave functions
var SaveQueue = []; // contains id's to the DOM object where the value can be found
var SaveQueueID = []; // contains id's for binding references (not always the same)
function ArrayContains(arr, value) {
for (i = 0; i < arr.length; i++) {
if (arr[i] == value)
return true;
}
return false;
}
function GetShortTime() {
var a_p = "";
var d = new Date();
var curr_hour = d.getHours();
if (curr_hour < 12)
a_p = "AM";
else
a_p = "PM";
if (curr_hour == 0)
curr_hour = 12;
else if (curr_hour > 12)
curr_hour = curr_hour - 12;
var curr_min = d.getMinutes();
curr_min = curr_min + "";
if (curr_min.length == 1)
curr_min = "0" + curr_min;
return curr_hour + ":" + curr_min + " " + a_p;
}
function Saved(result) {
if (result == "OK") {
document.getElementById("divAutoSaved").innerHTML = "Application auto-saved at " + GetShortTime();
document.getElementById("divAutoSaved").style.display = "";
}
else {
document.getElementById("divAutoSaved").innerHTML = result;
document.getElementById("divAutoSaved").style.display = "";
}
}
function getQueryString(name, defaultValue) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == name) {
return pair[1];
}
}
return defaultValue;
}
function urlencode(str) {
return escape(str).replace(/\+/g, '%2B').replace(/%20/g, '+').replace(/\*/g, '%2A').replace(/\//g, '%2F').replace(/#/g, '%40');
}
function AutoSave() {
if (SaveQueue.length > 0) {
var url = "/AjaxAutoSave.aspx?step=" + getQueryString("step", "ContactInformation");
for (i = 0; i < SaveQueue.length; i++) {
switch (document.getElementById(SaveQueue[i]).type) {
case "radio":
if (document.getElementById(SaveQueue[i]).checked)
url += "&" + SaveQueueID[i] + "=" + urlencode(document.getElementById(SaveQueue[i]).value);
break;
case "checkbox":
if (document.getElementById(SaveQueue[i]).checked)
url += "&" + SaveQueueID[i] + "=" + urlencode(document.getElementById(SaveQueue[i]).value);
default:
url += "&" + SaveQueueID[i] + "=" + urlencode(document.getElementById(SaveQueue[i]).value);
}
}
SaveQueue = [];
SaveQueueID = [];
AjaxSend(url, Saved);
}
}
function AddToQueue(elem, id) {
if (id == null || id.length == 0)
id = elem.id;
if (!ArrayContains(SaveQueueID, id)) {
SaveQueue[SaveQueue.length] = elem.id;
SaveQueueID[SaveQueueID.length] = id;
}
}
Add this to your page to make this work:
window.setInterval("AutoSave()", 5000);
And to apply this to a Textbox, DropdownList, Listbox, or Checkbox you just need to add this attribute:
onchange="AddToQueue(this)"
...or this for a RadioButtonList or CheckBoxList:
onchange="AddToQueue(this, '" + this.ClientID + "')"
I'm sure this Javascript could be simplified quite a bit if you used JQuery so you might want to consider that. But in any case, AJAX is the thing to use. It's what Google uses to auto-save your email message in gmail, and the same thing is in blogger when you're writing a new post. So I took that concept and applied it to a huge ASP.NET application with hundreds of form elements and it all works beautifully.
Use the Timer class and the Tick method.

AsyncFileUpload Control

I am using the new AsyncFileUpload control from the latest AjaxControl ToolKit.
My query is regarding the OnClientUploadStarted event which is fired before the upload is started. Is there any way to cancel the upload, as I am checking the fileExtension at this point and would like to cancel the upload so that it does not continue and go on to upload the file. My end result is allow only images to be uploaded.
Please advise and thanks for your time.
Got the answer, all I had to do was override the javascript function with this script(not the best answer, but works), you all could have done faster and cleaner
var orig = AjaxControlToolkit.AsyncFileUpload.prototype.raiseUploadStarted;
AjaxControlToolkit.AsyncFileUpload.prototype.raiseUploadStarted = function(e) {
var evt = this.get_events()._getEvent('uploadStarted');
if (evt) {
if (evt.length > 1)
return orig(e);
else if (evt.length === 1)
return evt[0](this, e);
}
}
You might try adding a "Regular Expression Validator" to the field, and see if you can use that to validate the file selected before the upload starts.
Try this code:
protected void AsyncFileUpload1_UploadedComplete(object sender, AjaxControlToolkit.AsyncFileUploadEventArgs e)
{
if (rdoFileType.SelectedValue == String.Empty)
{
lblStatus.Text = "Please select a file type before selecting a file.";
AsyncFileUpload1.FailedValidation = true;
e.state = AjaxControlToolkit.AsyncFileUploadState.Failed;
return;
}
try
{
// System.Threading.Thread.Sleep(5000);
if (AsyncFileUpload1.HasFile)
{
string _filename = System.IO.Path.GetFileName(e.filename);
System.IO.FileInfo f = new System.IO.FileInfo(AsyncFileUpload1.PostedFile.FileName);
if (rdoFileType.SelectedValue == "F")
{
if (f.Extension != ".pdf")
{
lblStatus.Text = "Final Document must be a .pdf";
e.state = AjaxControlToolkit.AsyncFileUploadState.Failed;
e.statusMessage = "Final Document must be a .pdf";
throw new Exception("Final Document must be a .pdf");
}

Resources