Silverlight - Exception when trying to POST to webservice - silverlight

I'm using the "Post" method so I can send a custom object. But I keep getting the following exception on the request.BeginGetResponse():
{System.Net.ProtocolViolationException: Operation is not valid due to the current state of the object.
at System.Net.Browser.BrowserHttpWebRequest.BeginGetResponseImplementation()}
public void Send()
{
HttpWebRequest client = WebRequest.Create(new Uri(BaseUrl)) as HttpWebRequest;
client.Method = "POST";
client.ContentLength = MaxSerializationSize;
client.BeginGetRequestStream(new AsyncCallback(RequestProceed), client);
}
private void RequestProceed(IAsyncResult asuncResult)
{
HttpWebRequest request = (HttpWebRequest) asuncResult.AsyncState;
StreamWriter postDataWriter = new StreamWriter(request.EndGetRequestStream(asuncResult));
MemoryStream ms = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(MyCustomClass));
ser.WriteObject(ms, MyCustomClassObject);
postDataWriter.Write(ms);
postDataWriter.Close();
request.BeginGetResponse(new AsyncCallback(ResponceProceed), request);
}
private void ResponceProceed(IAsyncResult asuncResult)
{
var request = (HttpWebRequest) asuncResult.AsyncState;
using (var resp = (HttpWebResponse) request.EndGetResponse(asuncResult))
{
using (var stream = resp.GetResponseStream())
{
}
}
}
I have tried so many ways to get this to work. Hoping someone can tell me where i'm going wrong. Thanks.

You need to close the request stream. You are just closing the StreamWriter and not the underlying request stream. While you are at it eliminate the superflous MemoryStream and have the DataContractJsonSerializer write directly to the Request stream.
HttpWebRequest request = (HttpWebRequest) asuncResult.AsyncState;
using (Stream outStream = request.EndGetRequestStream(asyncResult));
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(MyCustomClass));
ser.WriteObject(outStream, MyCustomClassObject);
outStream.Flush();
outStream.Close();
}
request.BeginGetResponse(new AsyncCallback(ResponceProceed), request);
Also get rid of this line:-
client.ContentLength = MaxSerializationSize;
Without also turning off AllowWriteStreamBuffering (which is only possible on the ClientHTTP implementation anyway) there is no need to set the ContentLength, that is done for you.

Related

SPFiles to .zip

As the title sugests, I have a list of SPFiles (sharepoint attachments) and I need to compress it and push to user download it.
I`ve looked for some examples here and tryed to code something but yet no success.
Here follow my last try until now
using (var stream = new MemoryStream())
{
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
{
foreach (SPFile item in lstFiles)
{
//string nomeEntrada = item.Substring(item.LastIndexOf("/") + 1);
var file = archive.CreateEntry(item.Name);
using (var entryStream = file.Open())
using (var streamWriter = new BinaryWriter(entryStream))
{
byte[] bytes = item.OpenBinary();
streamWriter.Write(bytes, 0, bytes.Length);
}
}
}
//For testing only, to check if the .zip is beeing correctly generated
using (FileStream file = new FileStream("C:\\teste\\file.zip", FileMode.Create, System.IO.FileAccess.Write))
{
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(file);
}
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/x-zip-compressed";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=anexos.zip");
HttpContext.Current.Response.BinaryWrite(stream.ToArray());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Close();
HttpContext.Current.ApplicationInstance.CompleteRequest();
HttpContext.Current.Response.End();
}
PS: I do not want to save the file in server directory, that was just a test to check if the file was OK
I created an Application Page and redirected user to it. Since I can control the httpcontext by there, I coded the following and it worked just fine. The page quickly stream the file to client and them close itself. Hope it helps
using (var stream = new MemoryStream())
{
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
{
foreach (SPFile item in lstFiles)
{
var file = archive.CreateEntry(item.Name);
using (var entryStream = file.Open())
using (var streamWriter = new BinaryWriter(entryStream))
{
byte[] bytes = item.OpenBinary();
streamWriter.Write(bytes, 0, bytes.Length);
}
}
}
stream.Seek(0, SeekOrigin.Begin);
Byte[] byteArray = stream.ToArray();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.CacheControl = "public";
HttpContext.Current.Response.AddHeader("Pragma", "public");
HttpContext.Current.Response.AddHeader("Expires", "0");
HttpContext.Current.Response.AddHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
HttpContext.Current.Response.AddHeader("Content-Description", "Report Export");
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"Anexos.zip\"");
HttpContext.Current.Response.BinaryWrite(byteArray);
HttpContext.Current.Response.Flush(); // Sends all currently buffered output to the client.
HttpContext.Current.Response.SuppressContent = true; // Gets or sets a value indicating whether to send HTTP content to the client.
HttpContext.Current.ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.
}

Issue in GetResponseStream() when getting results from Google Image

string requestUri = string.Format("http://images.google.com/images?q={0}&ndsp={1}&start={2}&filter={3}&safe={4}",query,RESULTS_PER_QUERY.ToString(),(startPosition+i).ToString(), (filterSimilarResults)?"1":"0",safeSearchStr);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
string resultPage = string.Empty;
using (HttpWebResponse httpWebResponse = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = httpWebResponse.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
resultPage = reader.ReadToEnd();
}
}
}
Above is my code and I'm getting the issue below.
responseStream.Length as 'responseStream.Length' threw an exception of type 'System.NotSupportedException'
responseStream.Position as 'responseStream.Position' threw an exception of type 'System.NotSupportedException'
Try using the WebClient.DownloadData method, it's way more simple. If the problem still occurs, I would recommend using Fiddler to inspect whether the call was made (and what was returned).

RestSharp - Download / Use image in WPF/Silverlight

I'm trying to use RestSharp to download an image from a WCF/Rest service. The result should be saved in a file and displayed in a Image control an a WPF/SL page.
private void GetImage()
{
RestClient _Client = new RestClient(BASE_URI);
RestRequest request = new RestRequest("/api/img/{FileName}");
request.AddParameter("FileName", "dummy.jpg", ParameterType.UrlSegment);
_Client.ExecuteAsync<MemoryStream>(
request,
Response =>
{
if (Response != null)
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = Response.Data;
String fn = String.Format(#"c:\temp\{0}.jpg", Guid.NewGuid().ToString());
System.IO.File.WriteAllBytes(fn,Response.Data.ToArray());
bitmapImage.EndInit();
img.Source = bitmapImage;
}
});
}
When I look in fiddler the image got downloaded correctly BUT no image is saved and nothing is displayd. There is no exception thown. ANy suggestions ?
UPDATED
A part of the problem turns out that RestSharp is not returning the expected memorystream. Moving to another methed and accessing the raw data in byte[] format solves part of the problem, saving the picutere to disk.
private void GetImage()
{
RestClient _Client = new RestClient(BASE_URI);
RestRequest request = new RestRequest("/api/img/{FileName}");
request.AddParameter("FileName", "dummy.jpg", ParameterType.UrlSegment);
_Client.ExecuteAsync(
request,
Response =>
{
if (Response != null)
{
byte[] imageBytes = Response.RawBytes;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(imageBytes);
bitmapImage.CreateOptions = BitmapCreateOptions.None;
bitmapImage.CacheOption = BitmapCacheOption.Default;
bitmapImage.EndInit();
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
Guid photoID = System.Guid.NewGuid();
String photolocation = String.Format(#"c:\temp\{0}.jpg", Guid.NewGuid().ToString());
encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
using (var filestream = new FileStream(photolocation, FileMode.Create))
encoder.Save(filestream);
this.Dispatcher.Invoke((Action)(() => { img.Source = bitmapImage; }));
;
}
});
}
Although calling this.dispatcher.Invoke I still get the error : The calling thread cannot acces this object because a different thread owns it.
As the BitmapImage is created in another thread than the UI thread, you also have to call Freeze to make it accessible in the UI thread.
Although not strictly necessary here, it is good practise to always dispose of any IDisposable objects, including MemoryStream. Therefore you will also have to set the BitmapImage.CacheOption property to OnLoad.
using (var memoryStream = new MemoryStream(imageBytes))
{
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
bitmapImage.Freeze();
}
The frozen BitmapImage is accessible in the UI thread:
Dispatcher.Invoke((Action)(() => img.Source = bitmapImage));
Are you checking for exceptions using the debugger? If an exception is thrown on a background task, it won't be rethrown on the caller code unless you access Task.Result or use the await operator.
My guess is that you don't have access to the location of C: you are writing to. That block of code seems unnecessary anyway though, you should be able to directly set the source of the image to the stream you have without writing it to disk. Try commenting the writing to drive piece of code out and see if that solves the issue.

Get stream from java.sql.Blob in Hibernate

I'm trying to use hibernate #Entity with java.sql.Blob to store some binary data. Storing doesn't throw any exceptions (however, I'm not sure if it really stores the bytes), but reading does. Here is my test:
#Test
public void shouldStoreBlob() {
InputStream readFile = getClass().getResourceAsStream("myfile");
Blob blob = dao.createBlob(readFile, readFile.available());
Ent ent = new Ent();
ent.setBlob(blob);
em.persist(ent);
long id = ent.getId();
Ent fromDb = em.find(Ent.class, id);
//Exception is thrown from getBinaryStream()
byte[] fromDbBytes = IOUtils.toByteArray(fromDb.getBlob().getBinaryStream());
}
So it throws an exception:
java.sql.SQLException: could not reset reader
at org.hibernate.engine.jdbc.BlobProxy.getStream(BlobProxy.java:86)
at org.hibernate.engine.jdbc.BlobProxy.invoke(BlobProxy.java:108)
at $Proxy81.getBinaryStream(Unknown Source)
...
Why? Shouldn't it read bytes form DB here? And what can I do for it to work?
Try to refresh entity:
em.refresh(fromDb);
Stream will be reopened. I suspect that find(...) is closing the blob stream.
It is not at all clear how you are using JPA here, but certainly you do not need to deal with Blob data type directly if you are using JPA.
You just need to declare a field in the entity in question of #Lob somewhat like this:
#Lob
#Basic(fetch = LAZY)
#Column(name = "image")
private byte[] image;
Then, when you retrieve your entity, the bytes will be read back again in the field and you will be able to put them in a stream and do whatever you want with them.
Of course you will need a getter and setter methods in your entity to do the byte conversion. In the example above it would be somewhat like:
private Image getImage() {
Image result = null;
if (this.image != null && this.image.length > 0) {
result = new ImageIcon(this.image).getImage();
}
return result;
}
And the setter somewhat like this
private void setImage(Image source) {
BufferedImage buffered = new BufferedImage(source.getWidth(null), source.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffered.createGraphics();
g.drawImage(source, 0, 0, null);
g.dispose();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
ImageIO.write(buffered, "JPEG", stream);
this.image = stream.toByteArray();
}
catch (IOException e) {
assert (false); // should never happen
}
}
}
You need to set a breakpoint on method org.hibernate.engine.jdbc.BlobProxy#getStream on line stream.reset() and examine a reason of IOException:
private InputStream getStream() throws SQLException {
try {
if (needsReset) {
stream.reset(); // <---- Set breakpoint here
}
}
catch ( IOException ioe) {
throw new SQLException("could not reset reader");
}
needsReset = true;
return stream;
}
In my case the reason of IOException was in usage of org.apache.commons.io.input.AutoCloseInputStream as a source for Blob:
InputStream content = new AutoCloseInputStream(stream);
...
Ent ent = new Ent();
...
Blob blob = Hibernate.getLobCreator(getSession()).createBlob(content, file.getFileSize())
ent.setBlob(blob);
em.persist(ent);
While flushing a Session hibernate closes Inpustream content (or rather org.postgresql.jdbc2.AbstractJdbc2Statement#setBlob closes Inpustream in my case). And when AutoCloseInputStream is closed - it rases an IOException in method reset()
update
In your case you use a FileInputStream - this stream also throws an exception on reset method.
There is a problem in test case. You create blob and read it from database inside one transaction. When you create Ent, Postgres jdbc driver closes InputStream while flushing a session. When you load Ent (em.find(Ent.class, id)) - you get the same BlobProxy object, that stores already closed InputStream.
Try this:
TransactionTemplate tt;
#Test
public void shouldStoreBlob() {
final long id = tt.execute(new TransactionCallback<long>()
{
#Override
public long doInTransaction(TransactionStatus status)
{
try
{
InputStream readFile = getClass().getResourceAsStream("myfile");
Blob blob = dao.createBlob(readFile, readFile.available());
Ent ent = new Ent();
ent.setBlob(blob);
em.persist(ent);
return ent.getId();
}
catch (Exception e)
{
return 0;
}
}
});
byte[] fromStorage = tt.execute(new TransactionCallback<byte[]>()
{
#Override
public byte[] doInTransaction(TransactionStatus status)
{
Ent fromDb = em.find(Ent.class, id);
try
{
return IOUtils.toByteArray(fromDb.getBlob().getBinaryStream());
}
catch (IOException e)
{
return new byte[] {};
}
}
});
}
My current and only solution is closing the write session and opening new Hibernate session to get back the streamed data. It works. However I do not know what is the difference. I called inputStream.close(), but that was not enough.
Another way:
I tried to call free() method of blob after session.save(attachment) call too, but it throws another exception:
Exception in thread "main" java.lang.AbstractMethodError: org.hibernate.lob.SerializableBlob.free()V
at my.hibernatetest.HibernateTestBLOB.storeStreamInDatabase(HibernateTestBLOB.java:142)
at my.hibernatetest.HibernateTestBLOB.main(HibernateTestBLOB.java:60)
I am using PostgreSQL 8.4 + postgresql-8.4-702.jdbc4.jar, Hibernate 3.3.1.GA
Is the method IOUtils.toByteArray closing the input stream?

Using httpwebrequest to get image from website to byte[]

I want to read the raw binary of a PNG file on a website and store it into a byte[], so far I have something like this:
Uri imageUri = new Uri("http://www.example.com/image.png");
// Create a HttpWebrequest object to the desired URL.
HttpWebRequest imgRequest = (HttpWebRequest)WebRequest.Create(imageUri);
using (HttpWebResponse imgResponse = (HttpWebResponse)imgRequest.GetResponse())
{
using (BinaryReader lxBR = new BinaryReader(imgResponse.GetResponseStream()))
{
using (MemoryStream lxMS = new MemoryStream())
{
lnBuffer = lxBR.ReadBytes(1024);
while (lnBuffer.Length > 0)
{
lxMS.Write(lnBuffer, 0, lnBuffer.Length);
lnBuffer = lxBR.ReadBytes(1024);
}
lnFile = new byte[(int)lxMS.Length];
lxMS.Position = 0;
lxMS.Read(lnFile, 0, lnFile.Length);
}
}
}
but I can't use GetResponse on Silverlight because it is not Asynchronous (I think that's the reason) so instead I should be using BeginGetResponse, but I'm not completely clear on how to go about it. This is what I have so far:
HttpWebResponse imgResponse = (HttpWebResponse)imgRequest.BeginGetResponse(new AsyncCallback(WebComplete), imgRequest);
using (imgResponse)
{
using (BinaryReader lxBR = new BinaryReader(imgResponse.GetResponseStream()))
{
/*Same*/
}
}
and
void WebComplete(IAsyncResult a)
{
HttpWebRequest req = (HttpWebRequest)a.AsyncState;
HttpWebResponse res = (HttpWebResponse)req.EndGetResponse(a);
//...? Do I need something else here?
}
can someone explain me a little bit how to use the BeginGetResponse property and how do I use the AsyncCallback.
Thanks!
Note:
I'm new to silverlight and I've been following tutorials and borrowing from other responses here on StackOverflow:
(stackoverflow responce) what I need to do but not in silverlight
tutorial
WebRequest_in_Silverlight
is this valid Silverlight code?
HttpWebResponse imgResponse = (HttpWebResponse)imgRequest.BeginGetResponse(new AsyncCallback(WebComplete), imgRequest);
Got it working, want to post it here in case anyone needs it.
I need to get this image and then modify it (byte level) Silverlight didn't let me save the image directly to a WriteableBitmap and thus I had to get the image with a WebClient as a stream and then save it to a byte[]
this is how I get the image (I already have the specific Uri):
WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(uri)
so when the image is loaded the wc_OpenReadCompleted method is called and it does something like this:
int lengthInBytes = Convert.ToInt32(e.Result.Length);
BinaryReader br = new BinaryReader(e.Result);
byte[] buffer = new byte[lengthInBytes];
using (br)
{
for (int i = 0; i < lengthInBytes; i++)
{
buffer[i] = br.ReadByte();
}
}
at the end the buffer[] has all the bytes of the image (what I wanted)
I'm sure there are better ways of doing this but this is working for me ! )
note: at some point I need to convert the byte[] to a BitmapImage (that was easier than expected):
//imageInBytes is a byte[]
if (imageInBytes != null)
{
MemoryStream rawBytesStream = new MemoryStream(imageInBytes);
BitmapImage img = new BitmapImage();
img.SetSource(rawBytesStream);
return img;
}
I hope this helps anyone.
Use the OpenReadAsync method of the WebClient object. Attach to the OpenReadCompleted event of the WebClient. Use the Stream provided by the Result property of the event args.
Consider setting AllowReadStreamBuffering, this will fill the entire stream before raising the OpenReadCompleted. In either case its likely you can use this stream to complete you real task rather than coping it into a MemoryStream.

Resources