Any help will be appreciated!
We have some browser based InfoPath (admin approved) form with code behind.
I've got some business task, that when user types some VAT ID, there is required to check if the VAT ID is valid or not and return info as message box.
OK, I've used some web service call to VIES.
string dicValue = FormMethods.GetIpFieldValue(currentForm, formFields.PoDicIPField);
string countryCode = dicValue.Substring(0, 2);
string vatId = dicValue.Substring(2, (dicValue.Length - 2));
this.DataConnections["WebServices-Query-SOAP-CheckVat"].Execute();
bool isVatValid = FormMethods.CheckVAT(this.DataSources);
string notification = "This VAT is valid.";
if (isVatValid != true)
{
notification = "This VAT is not valid!";
}
Then I've tried to send an alert back to page.
HttpContext currentContext = System.Web.HttpContext.Current;
currentContext.Response.Write("<script type=\"text/javascript\">alert('" + notification + "'); </script>");
OK alert
And my problem starts after the user cliks "OK" at alert (loosing page content).
Page look likes this
Because when InfoPath form loads, it loads context of "FormServer.aspx" page.
When User Clicks on button, InfoPath form gets context of PostBack.FormServer.aspx page.
So I need to:
Store original response OutputStream from load
Send an alert
Rewrite currentContext.Response by original response from load
But when I try to save currentContext.Response.OutputStream in any object (for example byte[]), I'm getting following exception: "Stream was not readable".
byte[] currentContextResponseOutputStreamBytes = null;
using(Stream stream = currentContext.Response.OutputStream)
using (MemoryStream memoryStream = new MemoryStream())
{
stream.Dispose();
int count = 0;
do
{
byte[] buffer = new byte[1024];
count = stream.Read(buffer, 0, 1024);
memoryStream.Write(buffer, 0, count);
}
while (stream.CanRead && count > 0);
currentContextResponseOutputStreamBytes = memoryStream.ToArray();
}
Could you help me please with this task?
Thanks
The problem seems to be pretty trivial here. You first invoke dispose on your stream object and then try to read it. This cannot work, because dispose 'destroys' the stream, so there is nothing more to read. This is why you get the exception.
To get rid of the problem, simply remove the dispose invocation. It should be executed at the end, not at the beginning! Moreover, you don't need it at all, because dispose will be executed automatically at the end of the using block.
Related
I have a simple client-server system sending plain text - though only commands that have been approved. The server is a Python system - and I've confirmed proper connections.
However, the client is C# - in Unity. Searching for examples, I stumbled across this bit of code. It does seem to do what I want, however, only partially:
public String readSocket()
{
if (!socketReady)
return "";
if (theStream.DataAvailable)
return theReader.ReadLine();
return "";
}
The strings I am sending end with \n, but I'm only getting half the message like this:
Message A:
claim_2
Message B:
_20_case
claim_1
I know this probably has to do with how I'm directly reading the line but I cannot find any better examples - strangely enough, everyone seems to point back at this snippet even when multiple people point out the problems.
Can anything be done to fix this bit of code properly?
In case it helps, I'm sending the information (from my Python server) out like this:
action = str(command) + "_" + str(x) + "_" + str(userid) + "_" + str(user)
cfg.GameSendConnection.sendall((action + "\n").encode("utf-8"))
When you do sockets programming, it is important to note that data might not be
available in one piece. In fact, this is exactly what you are seeing. Your
messages are being broken up.
So why does ReadLine not wait until there's a line to read?.
Here's some simple sample code:
var stream = new MemoryStream();
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream) { AutoFlush = true };
writer.Write("foo");
stream.Seek(0, SeekOrigin.Begin);
Console.WriteLine(reader.ReadLine());
Note that there is no newline at the end. Still, the output of this little
snippet is foo.
ReadLine returns the string up to the first line break or until there is no
more data to read. The exception being reading from a stream that has no more
data to read, then it returns null.
When a NetworkStream has its DataAvailable property return true, it has
data. But as mentioned before, there is no guarantee whatsoever about what that
data is. It might be a single byte. Or a part of a message. Or a full message
plus part of the next message. Note that depending on the encoding, it could
even be possible to receive only part of a character. Not all character
encodings have all characters be at most a single byte. This includes UTF-8, which cfg.GameSendConnection.sendall((action + "\n").encode("utf-8")) sends.
How to solve this? Read bytes, not lines. Put them in some buffer. After every
read, check if the buffer contains a newline. If it does, you now have a full
message to handle. Remove the message up to and including the newline from the
buffer and keep appending new data to it until the next newline is received. And
so on.
This is how I process the entire line in my similar application, which is a very simple code, and your code may be different, but you can get the idea.
private string incompleteRecord = "";
public void ReadSocket()
{
if (_networkStream.DataAvailable)
{
var buffer = new byte[8192];
var receivedString = new StringBuilder();
do
{
int numberOfBytesRead = _networkStream.Read(buffer, 0, buffer.Length);
receivedString.AppendFormat("{0}", Encoding.UTF8.GetString(buffer, 0, numberOfBytesRead));
} while (_networkStream.DataAvailable);
var bulkMsg = receivedString.ToString();
// When you receive data from the socket, you can receive any number of messages at a time
// with no guarantee that the last message you receive will be complete.
// You can receive only part of a complete message, with next part coming
// with the next call. So, we need to save any partial messages and add
// them to the beginning of the data next time.
bulkMsg = incompleteRecord + bulkMsg;
// clear incomplete record so it doesn't get processed next time too.
incompleteRecord = "";
// loop though the data breaking it apart into lines by delimiter ("\n")
while (bulkMsg.Length > 0)
{
var newLinePos = bulkMsg.IndexOf("\n");
if (newLinePos > 0)
{
var line = bulkMsg.Substring(0, newLinePos);
// Do whatever you want with your line here ...
// ProcessYourLine(line)
// Move to the next message.
bulkMsg = bulkMsg.Substring(line.Length + 1);
}
else
{
// there are no more newline delimiters
// so we save the rest of the message (if any) for processing with the next batch of received data.
incompleteRecord = bulkMsg;
bulkMsg = "";
}
}
}
}
I have refresh button. On refresh, I need to download a file and de-serialize its contents to read the information in it. Below is the method used to download the file.
public void DownloadVersionContents(long fileID,string fileName)
{
if (File.Exists(path))
{
File.Delete(path);
}
Stream stream = service.DownloadContent(fileID);
using (FileStream fileStream = File.OpenWrite(fileName))
{
// Write the stream to the file on disk.
var buf = new byte[1024];
int numBytes;
while ((numBytes = stream.Read(buf, 0, buf.Length)) > 0)
{
fileStream.Write(buf, 0, numBytes);
}
fileStream.Close();
}
stream.Close();
}
Everytime the refresh button is clicked, I have to delete the file and download latest file from the server. If the refresh is called with in a second or two im getting an error saying
System.IO.IOException was caught
HResult=-2147024864
Message=The process cannot access the file 'C:\Users\...\AppData\Local\Temp\mapping - copy.xml' because it is being used by another process.
Source=mscorlib
StackTrace:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.InternalDelete(String path, Boolean checkHost)
at System.IO.File.Delete(String path)
If the refresh is called after at least 10 or 20 seconds,im not getting any error. The file is never opened nor used yet. Kindly help.
Edit:
Sorry I forgot to mention, Im de-serializing the file using this method immediately after refresh is called.
public static T DeSerializeFromFile<T>(string xmlFilePath)
{
T instance = default(T);
if (xmlFilePath != null)
{
var reader = new StreamReader(xmlFilePath);
var serializer = new XmlSerializer(typeof(T));
instance = (T)serializer.Deserialize(reader);
}
return instance;
}
The refresh button is called again after the values are updated.
This seems like a good time to use a try catch-block. Catch the exception and prompt the user if the file is busy.
try
{
if (File.Exists(path))
File.Delete(path);
using(Stream stream = service.DownloadContent(fileID))
{
using (FileStream fileStream = File.OpenWrite(fileName))
{
// Write the stream to the file on disk.
var buf = new byte[1024];
int numBytes;
while ((numBytes = stream.Read(buf, 0, buf.Length)) > 0)
{
fileStream.Write(buf, 0, numBytes);
}
}
}
}
catch (IOException e)
{
MessageBox.Show("The refresh failed, try again in a few seconds.");
}
This wont speed up the refresh process but it will prevent the user from crashing your program by spamming refresh. Try to always have this kind of exception handling present when working with outside sources.
It sounds like the file takes longer than a couple seconds to get written. If the file is still being written to, then no, you certainly won't be able to delete it. You have a couple options.
The simplest, and probably best, is to keep track of whether you're still writing to it.
private bool IsWriting = false;
public void DownloadVersionContents(long fileID, string fileName)
{
if (!IsWriting)
{
IsWriting = true;
// Perform the delete and download
IsWriting = false;
}
}
Depending on the platform, you might want to reflect this in the UI as well, perhaps by disabling the "Refresh" button. This, of course, is assuming the file doesn't change more frequently than the time it takes to update. If it does, you may want to implement some cancellation pattern.
Beyond that, you could buffer the file directly into memory, then write it "all at once," which would probably only take a fraction of a second. Of course, if it's a big file, that won't be feasible.
Here is my java script code to choose file from dropbox, When I try to save this file to server using C# I am able to see file on server but it is empty.when I am trying to open file the file is giving error like 'file is corrupted'. using signalR.
options = {
// Required. Called when a user selects an item in the Chooser.
success: function (files) {
alert("Here's the file link: " + files[0].link)
hub.server.servermethod(files[0].link, files[0].name);
},
// Optional. Called when the user closes the dialog without selecting a file
// and does not include any parameters.
cancel: function () {
},
// Optional. "preview" (default) is a preview link to the document for sharing,
// "direct" is an expiring link to download the contents of the file. For more
// information about link types, see Link types below.
linkType: "preview", // or "direct"
// Optional. A value of false (default) limits selection to a single file, while
// true enables multiple file selection.
multiselect: false, // or true
// Optional. This is a list of file extensions. If specified, the user will
// only be able to select files with these extensions. You may also specify
// file types, such as "video" or "images" in the list. For more information,
// see File types below. By default, all extensions are allowed.
extensions: ['.csv', '.xls', '.tsv', '.xlsx', '.txt'],
};
var button = Dropbox.createChooseButton(options);
$('#container').append(button);
function some() {
Dropbox.choose(options);
}
server Method code is
// execute the request
HttpWebResponse response = (HttpWebResponse)
request.GetResponse();
// we will read data via the response stream
Stream resStream = response.GetResponseStream();
string tempString = null;
int count = 0;
Byte[] buffer = new Byte[32 * 1024];
StringBuilder sb = new StringBuilder();
do
{
// fill the buffer with data
count = resStream.Read(buffer, 0, buffer.Length);
// make sure we read some data
if (count != 0)
{
// translate from bytes to ASCII text
tempString = Encoding.ASCII.GetString(buffer, 0, count);
// continue building the string
sb.Append(tempString);
}
}
while (count > 0); // any more data to read?
using (FileStream fs = File.Create(System.Configuration.ConfigurationManager.AppSettings.GetValues("DocumentPath").First().ToString() + fileName))
{
// Byte[] bufer = new Byte[32 * 1024];
fs.Write(buffer, 0, buffer.Length);
}
You're setting linkType to "preview", which gives you a link to a preview page for the file, and not the file content itself. If you want direct access to the file content, e.g., to immediately and programmatically download the content to your server, as it seems you're trying to do, you should use the "direct" linkType.
I'm attempting to write an Office Add-in for Microsoft Word (2007 and higher) using VSTO on Visual Studio 2010 and C#.
The add-in will insert images into the document that are downloaded from the internet (from a custom CGI script). These images update daily, so I have added a button to 'refresh' all the images from the server upon request. However, I'm not certain how to 'store' the original identifier for the image along with the image embedded in the document to know which image to get from the server. The identifier can be anywhere from a few characters to several hundred (~200) characters long, but are an ASCII identifier.
Currently I insert the picture like so:
public void InsertPictureFromIdentifier(String identifier)
{
Document vstoDocument = Globals.Factory.GetVstoObject(this.Application.ActiveDocument);
Word.Selection selection = this.Application.Selection;
if (selection != null && selection.Range != null)
{
// Insert the picture control
var picture = vstoDocument.Controls.AddPictureContentControl(selection.Range, "mypic");
// And update the image
UpdatePicture(picture, identifier);
}
}
Then UpdatePicture is called both on the initial insert, and upon refresh, to update the image:
public void UpdatePicture(PictureContentControl picture, string identifier)
{
const int BytesToRead = 1000000;
// Download the image from the scrip
var request = WebRequest.Create("http://my.server.com/graph.cgi?"+identifier);
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
var reader = new BinaryReader(responseStream);
var memoryStream = new MemoryStream();
Byte[] byteBuffer = new byte[BytesToRead];
// Transfer to a memory stream
var bytesRead = reader.Read(byteBuffer, 0, BytesToRead);
while (bytesRead > 0)
{
memoryStream.Write(byteBuffer, 0, bytesRead);
bytesRead = reader.Read(byteBuffer, 0, BytesToRead);
}
// Set the image from the memory stream
picture.Image = new System.Drawing.Bitmap(memoryStream);
}
As you can see I pass the identifier into update - but the question is how to get that identifier back from the 'picture' I've inserted the next day on a refresh. I've tried using the picture's Tag, but that is limited to 64 characters. I've even tried using the picture's Title property, but that seems to silently fail on some other maximum limit.
The identifier will need to be persisted between save / loads, move with the image in the document, and be invisible (I can't just add text after the image with the identifier).
I am an embedded system software developer for safety critical systems, so I am fairly new with C# but proficient in C-based languages.
To provide a little background, I have developed a Windows Form that interprets serial data packets sent from my embedded software through the serial port into meaningful debugging information.
What I want to do is display each byte of each packet in a TextBox Control. The textbox control that displays the packet information is actually a second form opened by the first form. Here's the code for the event handler that opens the second form from the first:
private void ShowRawSerialData(object sender, EventArgs e)
{
SendSerialDataToForm = true;
if (SerialStreamDataForm == null)
SerialStreamDataForm = new RawSerialDataForm();
SerialStreamDataForm.Instance.Show();
}
In the above code, the .Instance.Show() directive is a means by which I may open a new form if the form is closed, but not show a new form if the form is already open.
Then, in my serial data received event handler, I do this:
// Get bytes from the serial stream
bytesToRead = IFDSerialPort.BytesToRead;
MsgByteArray = new Byte[bytesToRead];
bytesRead = IFDSerialPort.Read(MsgByteArray, 0, bytesToRead);
// Now MsgByteArray has the bytes read from the serial stream,
// send to raw serial form
if (SendSerialDataToForm == true && SerialStreamDataForm != null)
{
SerialStreamDataForm.UpdateSerialDataStream(MsgByteArray);
}
Where MsgByteArray is the byte array of the serial packet received. And here is the code for UpdateSerialDataStream:
public void UpdateSerialDataStream(Byte[] byteArray)
{
String currentByteString = null;
currentByteString = BitConverter.ToString(byteArray);
currentByteString = "0x" + currentByteString.Replace("-", " 0x") + " ";
if (RawSerialStreamTextBox.InvokeRequired)
{
RawSerialStreamTextBox.Invoke(new SerialTextBoxDelegate(this.UpdateSerialDataStream), new object[] { byteArray });
}
else
{
RawSerialStreamTextBox.Text += currentByteString;
}
RawSerialStreamTextBox.Update();
}
The end result is that the value of RawSerialStreamTextBox.Text is correctly updated with the string I intend on adding to the text box! For example, if I pass the byte array {0x01, 0x7F, 0x7E}, then, through the debugger, I can see that the value of RawSerialStreamTextBox.Text = "0x01 0x7F 0x7E".
The problem is that the text box control itself does not show the newly added text. So even though I can confirm through the debugger that RawSerialStreamTextBox.Text = "0x01 0x7F 0x7E" the text box in Windows does not show "0x01 0x7F 0x7E" but rather, remains blank.
Any ideas for what might be happening here?
I would guess that you are setting the Text property on an instance other than the one that is actually being displayed. A sanity check would be something like
RawSerialStreamTextBox.Visible = false;
Does it disappear?
To simplify a little, I would have UpdateSerialDataStream return a string (or pass a string to an out parameter) so that your Event Handler would, instead, look like this:
// Get bytes from the serial stream
bytesToRead = IFDSerialPort.BytesToRead;
MsgByteArray = new Byte[bytesToRead];
bytesRead = IFDSerialPort.Read(MsgByteArray, 0, bytesToRead);
// Now MsgByteArray has the bytes read from the serial stream,
// send to raw serial form
if (SendSerialDataToForm == true && SerialStreamDataForm != null)
{
RawSerialStreamTextBox.Text = UpdateSerialDataStream(MsgByteArray);
}
And UpdateSerialDataStream would look something like this:
public string UpdateSerialDataStream(Byte[] byteArray)
{
String currentByteString = null;
currentByteString = BitConverter.ToString(byteArray);
currentByteString = "0x" + currentByteString.Replace("-", " 0x") + " ";
return currentByteString;
}
You'd have to move your code handling the display of the form around a little, but this would allow the form already containing the TextBox to handle the update on its own.