Problem statement: You have to initiate file download in the browser with target = _self and in case of error on the server side you should not navigate away from the current page.
Why there is a problem: You initiate navigation to a download page. In case of successfully obtaining file from a server – you stay on the original page and FF/IE download window is shown. In case when there is an error on server side – result of your navigation with target _self will be an error page shown.
Though code provided here has some specific to Silverlight pieces, the idea is generic enough.
First, lets prepare a client side on the “initiator” page:
<script type="text/javascript">
$(document).ready(function () {
$('#form1').append('<iframe id="downloadFrame" style="visibility: hidden; height: 0px; width: 0px; border: 0px"/>');
});
function InitiateDownload(url) {
$('#downloadFrame').attr('src', url);
}
</script>
Lets introduce a tiny helper class to wrap a call to InitiateDownload for Silverlight:
public static class JavascriptHelper
{
public const string DownloadFunctionName = "InitiateDownload";
public static void StartDownload(Uri targetUri)
{
HtmlPage.Window.Invoke(DownloadFunctionName, new object[] {targetUri.ToString()});
}
}
Now, we can call InitiateDownload from Silverlight (via a command here which is not required and don’t forget about cross domain hurdles if it is your case):
DownloadCommand = new DelegateCommand<string>(g =>
JavascriptHelper.StartDownload(downloadUrl));
That is enough to get to the download dialog:
But lets add an ability to show a message box in case of a server-side error:
Following shows an example of amended download page (providing a placeholder for error message):
<head runat="server">
<script src="scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p runat="server" id="ErrorHolder"></p>
</div>
</form>
<script type="text/javascript">
var errorText = $('p#ErrorHolder').text();
alert(errorText);
</script>
</body>
</html>
With code behind concept:
protected void Page_Load(object sender, EventArgs e)
{
try
{
// Do your regular download stuff
}
catch(Exception ex)
{
// TODO: Log and only show user friendly sanitized message
ErrorHolder.InnerText = ex.Message;
}
}
No comments:
Post a Comment