AsyncFileUpload Control - asp.net

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");
}

Related

Reload page after file download via Response

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.

Session does not save

I'm very new to ASP.NET so there is a high risk that I am missing something simple here, but I have a problem with my Session. When I click the "NewTurn" button the first time, it creates the player just as it should, however, when I click it again, somehow all the stats are back as if it got created again (stats such as "health" is back to max value) but I can see in debug mode that it only enters the "if == null" function ONCE.
I don't understand what I am doing wrong, here is the code:
protected void NewTurn_Click(object sender, ImageClickEventArgs e)
{
StartButton.Visible = false;
RulesLink.Visible = false;
NewTurnButton.Visible = true;
if (Session["PrevObject"] == null)
{
Character player = new Character(1);
Session["PrevObject"] = player;
}
Character prevObj = (Character)Session["PrevObject"];
prevObj = CreateCard(prevObj);
Session["PrevObject"] = prevObj;
}
EDIT: I found the error and it had nothing to do with the Session, I just returned the object without setting the correct values before sending it back. Thank you for your suggestions, though and I'm sorry to have wasted your time!
please check comment in your code
protected void NewTurn_Click(object sender, ImageClickEventArgs e)
{
StartButton.Visible = false;
RulesLink.Visible = false;
NewTurnButton.Visible = true;
if (Session["PrevObject"] == null)
{
Character player = new Character(1);
Session["PrevObject"] = player;
}
Character prevObj = (Character)Session["PrevObject"];
// I think here you made mistake
prevObj = CreateCard(prevObj);
// check here again using DEbug point
// and make sure prevObj not null
Session["PrevObject"] = prevObj;
}
You should have to mention the Property of the player will be assign to the Session["PrevObject"].
suppose I have the class such as
public class Character
{
public playtime{get;set;}
Character(int i)
{
playtime=i;
}
}
Now I will code as you mention:
protected void NewTurn_Click(object sender, ImageClickEventArgs e)
{
StartButton.Visible = false;
RulesLink.Visible = false;
NewTurnButton.Visible = true;
if (Session["PrevObject"] == null)
{
Character player = new Character(1);
//Here is a little change you will have to specify what shuold be assign to the Session //variable
Session["PrevObject"] = player.playtime;
}
Hope this will help you.
Vote if you find helpful
Thanks is always appreciated.

Execute JavaScript on radmenu click asp.net

I am using rad menu (telerik) in my website. the menu items are binding to menu in code behind. i take the navigate URL from database and the navigate URL will be sometimes a JavaScript like
js=OpenSupportWin();
Instead of page url.
So when I give this to navigateurl nothing is happening. please help me to solve this.
private void GenerateVerticalMenuTelerik(string pParentMenuId, RadMenuItem rmi)
{
List<DBMenus> ListVerticalMenus = new List<DBMenus>();
ListVerticalMenus = MenuGenerator.GetVerticalMainMenusFromNode(pParentMenuId, ClsLogin.Instance.IsAuthenticated());
if (ListVerticalMenus != null)
{
foreach (DBMenus asVertical in ListVerticalMenus)
{
try
{
bool IsSelectedVertical = (m_SelectedMenuPath.SelectedSubItemId == asVertical.SiteMapNodeId);
RadMenuItem rmItem = new RadMenuItem();
rmItem.Text = asVertical.WORDINGTextTitle;
rmItem.NavigateUrl = PII.ToolWeb.Tools.pkFunctions.GetPageLinkURL(asVertical.SiteMapNodeUrl);
rmi.Items.Add(rmItem);
}
catch (Exception ex)
{
}
}
}
}
string url_js = asVertical.SiteMapNodeUrl;
if (url_js.Contains("js"))
{
url_js = url_js.Replace("?js=", "");
url_js = url_js.Replace(";", "");
url_js = "javascript:" + url_js;
}
i wrote these lines of code and it works for me
Set your navigateUrl to something like this:
item.NavigateUrl = "javascript:OpenSupportWin();";

How can I use the ContextKeys property for the AjaxFileUpload control?

I started looking at the AjaxFileUpload control, specifically the ContextKeys property. However, I do not understand how to use it.
The documentation says of AjaxFileUpload that the ContextKeys is used to pass information to the server when a file is uploaded. But no examples are provided. Are there any examples online that I could look at?
Though such functionality not implemented (I believe it was planned but by some reasons was postponed), nothing protect you from implement it yourself. To do this you need to download AjaxControlToolkit source code and tweak it for your needs.
There will be a lot of points so you may to prepare a cup of coffee before :)
I'll show changes with name of file that must being changed.
Server/AjaxControlToolkit/AjaxFileUpload/AjaxFileUpload.cs file
First of all, add ContextKeys property to the AjaxFileUploadEventArgs.cs file (it located in same folder):
/// <summary>
/// Gets or sets the context keys.
/// </summary>
public string ContextKeys
{
get;
set;
}
After that open the AjaxFileUpload class code and change the OnPreRender method. Here is a part of this method with custom modifications:
var eventArgs = new AjaxFileUploadEventArgs(guid, AjaxFileUploadState.Success,
"Success", uploadedFile.FileName,
uploadedFile.ContentLength, uploadedFile.ContentType,
stream.ToArray());
// NEW CODE HERE
eventArgs.ContextKeys = this.Page.Request.Form["contextKeys"];
That's all changes in server code we need. Now we need to modify the Sys.Extended.UI.AjaxFileUpload client class (file AjaxFileUpload.pre.js )
Firstly let's modify _html5UploadFile method as below:
_html5UploadFile: function (fileItem) {
this._guid = Sys.Extended.UI.AjaxFileUpload.utils.generateGuid();
var uploadableFile = fileItem.get_fileInputElement();
var fd = new FormData();
fd.append("fileId", uploadableFile.id);
fd.append("Filedata", uploadableFile.file);
if (this.contextKeys) {
if (typeof this.contextKeys !== "string") {
this.contextKeys = Sys.Serialization.JavaScriptSerializer.serialize(this.contextKeys);
}
fd.append("contextKeys", this.contextKeys);
}
$common.setVisible(this._progressBar, true);
this._setDisableControls(true);
this._html5SetPercent(0);
this._setStatusMessage(String.format(Sys.Extended.UI.Resources.AjaxFileUpload_UploadingHtml5File, uploadableFile.file.name, Sys.Extended.UI.AjaxFileUpload.utils.sizeToString(uploadableFile.file.size)));
var url = this._postBackUrl;
if (url.indexOf("?") != -1)
url += "&";
else
url += "?";
this._webRequest = new Sys.Net.WebRequest();
this._executor = new Sys.Net.XMLHttpExecutor();
this._webRequest.set_url(url + 'contextkey=' + this._contextKey + '&guid=' + this._guid);
this._webRequest.set_httpVerb("POST");
this._webRequest.add_completed(this.bind(this._html5OnRequestCompleted, this));
//this._executor.add_load(this.bind(this._html5OnComplete, this));
this._executor.add_progress(this.bind(this._html5OnProgress, this));
this._executor.add_uploadAbort(this.bind(this._html5OnAbort, this));
this._executor.add_error(this.bind(this._html5OnError, this));
this._webRequest.set_executor(this._executor);
this._executor.executeRequest(fd);
}
As you can see above, we adding contextKeys to form data, posted with Ajax request.
The we need to modify the _uploadInputElement method:
_uploadInputElement: function (fileItem) {
var inputElement = fileItem.get_fileInputElement();
var uploader = this;
uploader._guid = Sys.Extended.UI.AjaxFileUpload.utils.generateGuid();
setTimeout(function () {
uploader._setStatusMessage(String.format(Sys.Extended.UI.Resources.AjaxFileUpload_UploadingInputFile, Sys.Extended.UI.AjaxFileUpload.utils.getFileName(inputElement.value)));
uploader._setDisableControls(true);
uploader.setThrobber(true);
}, 0);
var url = uploader._postBackUrl;
if (url.indexOf("?") != -1)
url += "&";
else
url += "?";
uploader._createVForm();
uploader._vForm.appendChild(inputElement);
if (this.contextKeys) {
if (typeof this.contextKeys !== "string") {
this.contextKeys = Sys.Serialization.JavaScriptSerializer.serialize(this.contextKeys);
}
var contextKeysInput = document.createElement("input");
contextKeysInput.setAttribute("type", "hidden");
contextKeysInput.setAttribute("name", "contextKeys");
contextKeysInput.setAttribute("value", this.contextKeys);
uploader._vForm.appendChild(contextKeysInput);
}
uploader._vForm.action = url + 'contextkey=' + this._contextKey + '&guid=' + this._guid;
uploader._vForm.target = uploader._iframeName;
setTimeout(function () {
uploader._vForm.submit();
uploader._waitTimer = setTimeout(function () { uploader._wait() }, 100);
}, 0);
}
After all these changes you can set ContextKeys property in code-behind and get it value from AjaxFileUploadEventArgs argument of the UploadComplete event as below:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack && !AjaxFileUpload1.IsInFileUploadPostBack)
{
AjaxFileUpload1.ContextKeys = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(new Dictionary<string, string> { { "1", "First" }, { "2", "Second" } });
}
protected void AjaxFileUpload1_OnUploadComplete(object sender, AjaxFileUploadEventArgs file)
{
if (!string.IsNullOrEmpty(file.ContextKeys))
{
var contextKeys = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Dictionary<string, string>>(file.ContextKeys);
}
Also, if you'll implement OnClientUploadStarted client-side event as proposed here link, you may pass to server your contextKeys from client:
function uploadStarted(sender, args) {
sender.contextKeys = { "first": "1", "second": "2" };
}

ASP:TextBox Value disappears in postback only when password

I have an asp.net textbox like this:
<asp:TextBox ID="PINPad" runat="server" Columns="6" MaxLength="4"
CssClass="PINTextClass"></asp:TextBox>
It is, as you might have guessed, the text box from an on screen PIN pad. Javascript fills in the values. The page is posted back every five seconds (using an update panel if that matters) to update various other unrelated items on the screen. This works just fine.
However, when I convert it to a password text box, like this:
<asp:TextBox ID="PINPad" runat="server" Columns="6" MaxLength="4"
CssClass="PINTextClass" TextMode="Password"></asp:TextBox>
Then whenever the page posts back, the text box is cleared out on the screen and the textbox is empty (though during the timer event, the value does make it back to the server.)
Any suggestions how to fix this, so that it retains its value during postback?
As a security feature, ASP.NET tries to disallow you from sending the password value back to the client. If you're okay with the security issues (i.e. it's either not really secure information or you're sure that the connection is secure), you can manually set the "value" attribute of the control, rather than using its Text property. It might look something like this:
this.PINPad.Attributes.Add("value", this.PINPad.Text);
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
if (!(String.IsNullOrEmpty(txtPwd.Text.Trim())))
{
txtPwd.Attributes["value"]= txtPwd.Text;
}
if (!(String.IsNullOrEmpty(txtConfirmPwd.Text.Trim())))
{
txtConfirmPwd.Attributes["value"] = txtConfirmPwd.Text;
}
}
}
here is another way to do it:-
using System;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebControlLibrary
{
public class PWDTextBox : TextBox
{
public PWDTextBox()
{
this.TextMode = TextBoxMode.Password;
}
public string Password
{
get
{
string val = (string)ViewState["pwd"];
if (string.IsNullOrEmpty(val))
{
return "";
}
else
{
return val;
}
}
set
{
ViewState["pwd"] = value;
}
}
public override string Text
{
get
{
return Password;
}
set
{
Password = value;
}
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
this.Text = Password;
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Password);
}
}
}
The problem of losing the password in the postback can be avoid making use of Asynchronous JavaScript calls, lets describe a typical scenario for a Login page:
Lets say we have a Login page which allows the user to change the language of its labels when the user choose a language with a dropdownlist
a solution would be to invoke selectedIndexChanged event of the dropdownlist, make a postback which goes to the server and picks up the labels in the chosen language.
in this scenario the field password will be lost due to the security feature of ASP.NET which makes passwords fields not persisted between a postbacks.
This scenario can be solved if the postback is avoided making use of Asynchronous JavaScript Technology and XML (Ajax) calls.
Add a javascript function which will be invoked from the dropdownlist control, in this case this function is assigned to the Command property of the dropdownlist in code behind:
function ValueChanged(div)
{
var table = div.getElementsByTagName("table");
if (table && table.length > 0)
{
var t = table[0].getAttribute('type');
if (t != null && (t == "DropDown"))
{
var inputs = div.getElementsByTagName("input");
if (inputs && inputs.length == 2)
{
{
Translate(inputs[1].value);
}
}
}
}
}
The Translate function takes as parameter the selected option language in the dropdown control and performs the asynchronous call as shown bellow.
function Translate(lang)
{
var request = null;
if (window.XMLHttpRequest)
{
request = new XMLHttpRequest();
if (request.overrideMimeType)
{
request.overrideMimeType('text/xml');
}
}
else if (window.ActiveXObject)
{
request = new ActiveXObject("Msxml2.XMLHTTP");
}
if (request == null)
{
return;
}
var url = "GetLoginTranslations.aspx";
request.open('GET', url +'?lang=' + lang, true);
request.setRequestHeader("Cache-Control", "no-cache");
request.setRequestHeader("Pragma", "no-cache");
request.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
request.onreadystatechange = function () { TranslateLabels(request); };
request.send(null);
}
the function Translate shown above performs the call and get the results in the specified .aspx page (in this case "GetLoginTranslations.aspx")
when the request is completed and the request.onreadystatechange is set to the function TranslateLabels this function will be executed.
on this way the postback is not executed as before in the event onSelectedIndexChanged of the dropdownlist control.
the TranslateLabels function would look something like :
function TranslateLabels(request)
{
if (request.readyState == 4)
{
if (request.status == 200)
{
if (request.responseXML)
{
var objRoot = request.responseXML.documentElement;
if (objRoot)
{
if (objRoot.nodeName == "strings")
{
for (var i = 0; i < objRoot.childNodes.length; i++)
{
var node = objRoot.childNodes[i];
var elem;
switch (node.getAttribute("id"))
{
case "lbl_login":
elem = document.getElementById("lbl_login");
if (elem)
elem.innerHTML = node.firstChild.nodeValue;
break;
}
///....
}
}
}
}
}
}
the request.responseXML contains the XML built in the page GetLoginTranslations.aspx and the structure of this XML is defined there.
the Page_Load() event in the GetLoginTranslations.aspx should look like:
protected void Page_Load(object sender, EventArgs e)
{
if (Request["lang"] != null)
strLang = Request["lang"];
//init response
Response.Clear();
Response.Cache.SetExpires(DateTime.Now);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetValidUntilExpires(true);
Response.ContentType = "application/xml";
Response.Charset = "utf-8";
XmlTextWriter xml = new XmlTextWriter(Response.OutputStream, System.Text.Encoding.UTF8)
{
Formatting = Formatting.None
};
xml.WriteStartDocument();
xml.WriteStartElement("strings");
xml.WriteStartElement("string");
xml.WriteAttributeString("id", "lbl_login");
xml.WriteString(GetTranslation("label_login", strLang));
xml.WriteEndElement();
// ... the other labels
xml.WriteEndElement(); //</strings>
xml.Close();
}
Some other considerations:
set the the property AutoPostback of the dropdownlist to false.
Happens both for view-model properties named 'Password' and 'PIN'. You can bypass the behavior by defining those as:
string Password ;
... rather than:
string Password { get; set; }
If you do so, features such the 'LabelFor' macro displaying 'DisplayAttribute.Name' no longer works, so you'd have to define those directly in the HTML.
Or you can simply name the fields something other than 'Password' or 'PIN'.

Resources