Silverlight SaveFileStream Silently Fails - silverlight-4.0

I have a little piece of code that seems to be a textbook example of saving files from Silverlight 4.0, but it doesn't seem to work.
The following snippet comes from a button click handler:
var saveDialog = new SaveFileDialog() { Filter = "All Files(*.*)|*.*" };
if (saveDialog.ShowDialog() == true)
{
using (var stream = saveDialog.OpenFile())
using (var writer = new StreamWriter(stream))
{
writer.WriteLine("Hello, World!");
writer.Flush();
writer.Close();
}
}
I've tried saving a file to many different locations, all with the same behavior:
The SaveFileDialog appears to behave normally.
The SaveFileStream appears (from the debugger) to behave normally.
After the call to writer.Flush(), the BaseStream advances to position 15.
No exception is thrown.
After the block executes, I cannot find the file using Windows Explorer.
It seems to me that the code is too simple to fail under normal circumstances. So that leads to my question: what is amiss with my circumstances? Why is it that the save appears to complete successfully, but the file is nowhere to be found? Security settings? The code itself? I'm at a loss.
Update
I've tried a few more things, and still no luck. I ran the application out-of-browser with the same symptoms, promoted the SaveFileDialog to a class variable. The application behaves like there is no error, but no file appears in the save location (my Documents folder, in Vista).
The Plot Thickens
I was stepping through with the debugger and found additional strange behavior. After the call to saveDialog.OpenFile(), the file appears at the target location. It remains after each statement, but is removed after the call to writer.Close(). Why on earth would the file be automagically deleted when the stream closes?
Thanks in advance for your help!

Related

Replacing Absolute file path by Resource file path

I created an add-in to an existing software (Revit) and I want to embed an image (my company's logo) in the add-in's button.
Here is my current code for it:
'Set the large image shown on button
Dim uriImage As New Uri("\\10.8.60.3\Shared\REVIT\FSElogo.png")
Dim largeImage As New BitmapImage(uriImage)
MainButton.LargeImage = largeImage
It works pretty well and the logo is correctly displayed, however it requires the computer to have access to the server located at \\10.8.60.3. When working from home, we do not have access to this server and Revit throws an error when starting because of it.
So I tried adding the FSElogo.png file to my VB.Net project as a Resource and then tried to use My.Resources to access the image, effectively removing the need for an external image to be used.
Well, I can't get it to work.
I tried replacing the code above by
MainButton.LargeImage = CType(My.Resources.ResourceManager.GetObject("FSElogo.png"), Windows.Media.ImageSource)
But it doesn't work. It doesn't throw an error, but no image is displayed on the button.
If I don't cast my Object to an ImageSource I get an implicit conversion from Object to Image error, and I'm not even sure my ResourceManager is even really returning the object FSElogo.png.
What am I doing wrong here?
I am using the VS provided button with the .BackgroundImage property. Notice that the extension of the file is not included in the resource identifier. If this doesn't work, you will have to explain exactly how you added the resource to your project.
MainButton.BackgroundImage = My.Resources.FSElogo

Open images from Windows store application

I have created a windows store application and I want the user to open Documents, Excel files and picture from the app. I want the files to open in their default application. i.e. Docs in word and pictures in windows picture viewer.
I have used the following code:
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add(".Doc");
openPicker.FileTypeFilter.Add(".Docx");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".jpg");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file!=null)
{
await Windows.System.Launcher.LaunchFileAsync(file);
}
When I run this and browse to a word document the file opens up fine using word, great.
But if I browse to an image file, it doesn't do anything. I don't get any errors.
Any ideas what I need to do?
Thanks
There is no error and, simply, nothing happens? That's strange.
Here's my go-to syntax, but it's basically yours:
Let's consider what should happen. When you "launch" a docx you are basically asking the default viewer to open for that file, in that case Word. With an image you are asking the image viewer to launch. Should it work? Yes.
Launching a docx when Word is not installed should not result in the behavior your are seeing. No. You should get prompted to find a viewer in the Store. Same with an image. Even without a viewer you should get something.
Not to be a dork here, but have you rebooted? It really sounds more like something strange has happened. You might also try appending "file:///" to the front of the URL to perhaps invoke the file viewer more explicitly. None of that should be necessary however.
Best of luck
One other thing you can do is to force app picker if default program could not be launched like following:
if (file != null)
{
var options = new Windows.System.LauncherOptions();
options.DisplayApplicationPicker = true;
bool success = await Windows.System.Launcher.LaunchFileAsync(file, options);
}

"Microsoft Edge PDF inline issue" Same Issue Again

I'm still having the same issue that was previously reported and answered under Microsoft Edge PDF inline issue even though I'm not using the pre-release version of Win 10, but the latest downloaded though Windows Update.
After upgrading my Win 8.1 Machine to Win 10, and tested my ASP.NET application, I faced an issue with displaying inline pdf files.
Here's my C# code in my ASP.NET application:
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition","inline;filename=some.pdf");
Response.BinaryWrite(pdfArray);
Response.End();
The above works on all browsers, except on Edge where it gives me the following error:
Couldn’t open PDF
Something’s keeping this PDF from opening.
What am I doing wrong?
Copied from my workaround on Microsoft Connect.
WARNING: This is a complete hack and runs the risk of breaking if/when Microsoft ever fixes this issue.
You'll see that Edge issues two requests whenever you view a PDF. To me, it looks like the browser is sending the initial request and then the PDF viewer is issuing its own request when it is opened. If you look at the headers in that second request, you'll see an odd DLNA header coming down, which should just be for media streaming, but that leads me to my workaround...
When the request is received in your handler or page, check if the user agent string contains "Edge/12." If it doesn't, send your PDF back normally. If it does, move on to step #2.
Check if the HTTP Header "GetContentFeatures.DLNA.ORG" exists. If it doesn't, that means that the request came from the browser. Just send back a Content-Type header of "application/pdf" and an empty body. If the header exists, then the request came from the PDF viewer and you can send your PDF back normally.
Basically, the handler treats that first request as a HEAD request and then responds with the full PDF if we determine that the request is coming from the PDF viewer. The risk we run here is if Microsoft removes that DLNA header later on, Edge will not render the PDF properly. Hopefully, Microsoft will fix this issue in their browser and this workaround will not be necessary.
Thanks Dark Helmet, you saved my day.
I implemented the solution in java. Here is the code that might help others.
String userAgent = request.getHeader("user-agent");
System.out.println(userAgent);
if(userAgent.contains("Edge")){
String dlnaHeader = request.getHeader("getcontentfeatures.dlna.org");
System.out.println(dlnaHeader);
if(dlnaHeader == null ){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] result = baos.toByteArray();
response.setContentType("application/pdf");
response.setHeader("Content-disposition","inline; ");
response.setContentLength(result.length);
ServletOutputStream sos = response.getOutputStream();
sos.write(result);
return null;
}
}
Thanks guys, I just want to put my VB.NET solution here based on your workaround.
Response.Clear()
Response.ClearHeaders()
Response.ClearContent()
Response.Buffer = True
If Request.Headers.Item("User-Agent").Contains("Edge") _
AndAlso IsNothing(Request.Headers.Item("GetContentFeatures.DLNA.ORG")) Then
'Edge? Send empty output if special header not exist
Response.ContentType = "application/pdf"
Dim bTemp As Byte()
Response.BinaryWrite(bTemp) 'Empty output
Response.Flush()
Response.SuppressContent = True
HttpContext.Current.ApplicationInstance.CompleteRequest()
End If
'Normal process:
Response.ContentType = "application/pdf"
Response.BinaryWrite(pdfArray)
Response.Flush()
Response.SuppressContent = True
HttpContext.Current.ApplicationInstance.CompleteRequest()
With Edge 16.16299 (Windows Fall Creator Update) there were made changes here. We did the workaround described in this issue and it worked "well". But now with the new version of Edge (16.16299) it isn’t working anymore and it happens, that the PDFs are corrupted (0 bytes large). Take care if you implemented this workaround somewhere.
What you also take care of is that Edge is doing two requests like before.

CreateFileAsync in SuspensionManager throws indecipherable exception

I created a new Windows Store app project using the Grid App (XAML) template. I ran the project (in debug mode) without changing a single line of code. While it was running, I switched back to Visual Studio and clicked the Suspend button in the toolbar.
At this point, the app threw a SuspensionManagerException. The exception’s details weren’t too helpful. The message is SuspensionManager failed. It has the (so far) unhelpful HResult -2146233088. It also has an InnerException that’s just as unhelpful. Its message is Error HRESULT E_FAIL has been returned from a call to a COM component. and its HResult, which is -2147467259, is even worse than the outer exception’s HResult.
The line of code that throws the exception is in the SuspensionManager, which, again, is part of the project template. Here’s the line:
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(sessionStateFilename, CreationCollisionOption.ReplaceExisting);
The part that triggers the exception is LocalFolder.CreateFileAsync(…). The MSDN documentation for the CreateFileAsync method has a “Remarks” section that reads: If you try to create a file in a virtual folder like a library or a file group, this method may fail.
That’s it. There’s no explanation of why it may fail, or a description of the conditions under which it may fail, or what you can do about it.
As it happens, even when it fails, the file is actually created. The file in question is called _sessionState.xml and is located at C:\Users\<username>\AppData\Local\Packages\<package_id>\LocalState. If I delete the file and re-suspend the app, the exception is throw again and the file is recreated.
I've searched high and low and haven't found anything conclusive. The CreateFileAsync method is a projection, so I can't easily disassemble it or figure out why it "may fail".
Does anybody have any idea what could be causing this problem, or how to go about debugging or solving it?
The first thing to check is that Frame.Navigate should only take primitives as its parameter argument.
Also, make sure you are calling GetDeferral in your async event handler.

How to best to cancel a Zend Form File Upload?

I am experimenting with uploading files in a Zend_Form using the Zend_Form_Element_File doing something like this in my form so that the actual upload can be handled by my controller (which in my case is to eventually do some custom file re-naming on the fly).
$element = new Zend_Form_Element_File('Upload');
$element->setDestination(UPLOAD_PATH)
->setValueDisabled(true);
$submit = new Zend_Form_Element_Submit('submit');
In the controller action I then have (very simplified) code like the following which works well:
$form = new MyForm();
$this->view->form = $form;
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
$form->Upload->receive();
$this->_redirect('/nextAction');
} else {
$form->populate($formData);
}
}
However (and here it comes) what I want to do is have a cancel button on my form handled like this:
[Form]
$cancel = new Zend_Form_Element_Submit('cancel');
[Controller]
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
$cancel = $this->getRequest()->getPost('cancel');
if ($cancel == 'Cancel') {
$this->_redirect('/nextAction');
}
if ($form->isValid($formData)) {
$form->Upload->receive();
$this->_redirect('/nextAction');
} else {
$form->populate($formData);
}
}
The trouble starts when the user selects a file via 'Upload' and then hits 'cancel' to exit out of the action. The form doesn't know the difference between 'Submit' and 'Cancel' and initiates the transfer from the browsers end. On the server end the receive() function isn't called and that hangs the entire process.
In this older (Non-Zend) SO question "Cancel a webform submit with php" the suggested answer is to have the cancel button in a separate form. I don't think that this is what I want to do in a Zend based system.
In this old (Zend) forum question "Zend Form Element File upload issues" the suggested answer for canceling an upload is to do something like this:
if ($cancel == 'Cancel') {
unlink($form->Upload->getValue());
$this->_redirect('/nextAction');
}
I have tried this and it seems to work, but I don't know why and when I look behind the curtains I actually see that it generates an error of the form:
Warning: unlink(<filename>): No such file or directory in <line in controller code where unlink() call is>
So my big question is what is the best way to be canceling out of the file upload? (and what does the unlink do - even with the error?)
Edit 3/3
To clarify, HTML form uploads are pretty dumb. If you have multiple submit buttons on a form that has a File element, then no matter what submit button you seem to use the file gets transferred to the temp upload directory on your server.
But Zend tries to be clever, it allows you to defer copying the file from the temp directory to the final destination through "setValueDisabled(true)" in the form and "receive()" in the controller.
However if you initiate an upload in the form, but do not call "receive() in the controller, then the entire Zend process seems to lock up (I get the browser continually announcing "loading" and doing nothing else).
I am looking for a Zend (or pure php) based solution to back out of the file upload on the server side, after the file has arrived in the temp directory, but before a call to "receive()" is required.
The "unlink" method seems to work, but it also throws a warning and as I have no real idea of why it works I am suspicious of what is actually going on.
Try if ($cancel->isChecked()) instead of if ($cancel == 'Cancel')
EDIT
This is how file uploads work. The form is submitted, and the browser sends the file, through HTTP to server. PHP sees a form with enctype "multipart/form-data" and a file element, and saves that file in a temporary location. At this point, if you call "Receive", it actually calls, behind the scenes, the PHP functions which move that file out of its temporary location.
Once you hit submit, the browser sends the file, whether you like it or not. You can choose to ignore the file, which is what it looks like you're trying to do. However, if ($cancel == 'Cancel'), doesn't look it will work because the value is case-sensitive. To avoid error-prone code like this, if ($cancel->isChecked()) is preferred.
Can you be a little more specific on what exactly you're trying to do?