I am sure this is an easy question however I am not finding the solution. I want to save the XML files posted to my .NET Web Service. I am sure it is just a simple method call when the service is invoked but I am not finding it. I would like to save the full XML posted to the service
Any help would be greatly appreciated. Thank you in advance.
Thank you for your help however I found what I was looking for at http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapextension.aspx
To help anyone else that is new to tring to implement this via WebService's I included the steps that I performed to implement it and modifications so I could save it to the db as well as the file system I performed the following steps. If you have any questions please feel free to aks and I will be happy to answer.
Created a code file in my web service project with the code listed in the in the article
Created a few properties to store values to save to the db
private string _requestXml;
private DateTime _start;
Then I modified the WriteInput method to save values to those variables.
public void WriteInput(SoapMessage message)
{
//Begin Edit
oldStream.Position = 0;
_requestXml = new StreamReader(_oldStream).ReadToEnd();
_start = DateTime.UtcNow;
//End Edit
//Begin Original Code
oldStream.Position = 0;
Copy(oldStream, newStream);
var fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
var w = new StreamWriter(fs);
var soapString = (message is SoapServerMessage) ? "SoapRequest" : "SoapResponse";
w.WriteLine("-----" + soapString + " at " + DateTime.Now);
w.Flush();
newStream.Position = 0;
Copy(newStream, fs);
w.Close();
newStream.Position = 0;
}
Then I modified the WriteOutput to
public void WriteOutput(SoapMessage message)
{
//Begin Edit
var responseXml = new StreamReader(newStream).ReadToEnd();
newStream.Position = 0;
//Start process for saving to DB
//"_requestXml" = Original Request Soap Message
//"responseXml" = Service Returned Response
//"_start" = Request Start Time
//message.MethodInfo.Name = I save this so I know what method from
//message.Url = I save this so I know the original ASMX that was hit
//End Edit
//Begin Original Code
newStream.Position = 0;
var fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
var w = new StreamWriter(fs);
var soapString = (message is SoapServerMessage) ? "SoapResponse" : "SoapRequest";
w.WriteLine("-----" + soapString + " at " + DateTime.Now);
w.Flush();
Copy(newStream, fs);
w.Close();
newStream.Position = 0;
Copy(newStream, oldStream);
}
Now all that's left is to add the following to your service call and you should be good to go
[WebMethod, NameSpace.OfyourTraceExtesionClass.TraceExtension]
public void WebMethod1()
{
//DoSomeStuff
}
If you want to log the http post messages, an elegant way of solving it would be to set up a simple reverse proxy in front of your web services. In this proxy you would have full access to the raw http request.
XML file received as Stream
Convert Stream to byte[]
Convert byte[] to XDocument (System.Xml.Linq)
Read XDocument with LINQ syntax and save to DB
[WebMethod]
public void XMLPersing()
{
var XMLDATA = "";
WriteLogCLS objWriteLog = new WriteLogCLS();
Stream receiveStream = HttpContext.Current.Request.InputStream;
receiveStream.Position = 0;
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8); //For xml persing..
XMLDATA = readStream.ReadToEnd();
readStream.Close();
objWriteLog.WriteLog(Convert.ToString(XMLDATA));
XmlTextReader xmlreader = new XmlTextReader(Server.MapPath("Log/Exception/Sample.xml"));
DataSet ds = new DataSet();
ds.ReadXml(xmlreader);
xmlreader.Close();
if (ds.Tables.Count != 0)
{
var strCon = string.Empty;
strCon = ConfigurationManager.AppSettings["constring"];
SqlCommand cmdInsertXMLData = new SqlCommand();
SqlConnection SqlConn;
SqlConn = new SqlConnection(strCon);
try
{
cmdInsertXMLData = new SqlCommand("usp_InsertXML", SqlConn);
cmdInsertXMLData.CommandType = CommandType.StoredProcedure;
// cmdInsertLoginDetails.Parameters.Add("#XMLdata", SqlDbType.Xml).Value = ds.GetXml();
cmdInsertXMLData.Parameters.AddWithValue("#XMLdata", SqlDbType.Xml);
if (SqlConn.State == ConnectionState.Closed)
{
SqlConn.Open();
}
cmdInsertXMLData.ExecuteNonQuery();
// response = cmdInsertLoginDetails.Parameters["#Message"].Value.ToString();
}
catch (Exception ex)
{
objWriteLog.WriteLog("Error on XML Persing : " + ex.Message);
// response = "Error";
}
finally
{
if (cmdInsertXMLData != null)
{
cmdInsertXMLData.Dispose();
}
if (SqlConn.State == ConnectionState.Open)
{
SqlConn.Close();
SqlConn.Dispose();
}
objWriteLog = null;
}
// return response ;
}
}
}
Related
After several attempts I can't get StreamWriter to build / work corectly so I am doing something fundamentally wrong (C#, Visual Studio)
I have an exisitng TCP Client which connects and acts as a reader, this is working without fault -
private System.Net.Sockets.NetworkStream ns;
private System.IO.StreamReader sr;
private string strIP;
private string strPort;
public System.Net.Sockets.TcpClient tc;
public Socketclient(Reader.Search objSearch)
{
m_search = objSearch;
}
public void EthernetConnection()
{
try
{
bool flag = !System.IO.File.Exists(System.Windows.Forms.Application.StartupPath + "\\IPAddress.txt");
if (!flag)
{
System.IO.TextReader textReader = System.IO.File.OpenText(System.Windows.Forms.Application.StartupPath + "\\IPAddress.txt");
string s = textReader.ReadLine();
textReader.Close();
char[] chArr = new char[] { ';' };
string[] sArr = s.Split(chArr);
strPort = sArr[0];
strIP = sArr[1];
flag = strIP == System.String.Empty || strPort == System.String.Empty;
if (!flag)
{
int i = System.Convert.ToInt16(strPort);
tc = new System.Net.Sockets.TcpClient(strIP, i);
flag = !tc.Connected;
if (!flag)
{
ns = tc.GetStream();
sr = new System.IO.StreamReader(ns);
m_search.threadClient = new System.Threading.Thread(new System.Threading.ThreadStart(ReceiveData));
m_search.threadClient.Priority = System.Threading.ThreadPriority.Lowest;
m_search.threadClient.Name = "Ethernet Thread";
}
I then want to add (in another .cs which is part of the same application) a StreamWriter thread to write back some characters to the same port and then close the StreamWriter thread (leaving the reader running) -
private System.IO.StreamWriter sw;
string line = "TH1/r/n";
using (StreamWriter sw = new StreamWriter(ns));
sw.WriteLine(line);
sw.Flush();
sw.Close();
Which, somehow (I think) needs to refer back to
ns = tc.GetStream();
Any thougts appreciated
Regards
Active
this sort of question has been asked many times already.
Receving and sending data in C#
brief cut and past from example above showing sending of data
using(TcpClient tcpClient = new TcpClient("ADDRESS"))
{
NetworkStream networkStream = tcpClient.GetStream();
using(StreamWriter streamWriter = new StreamWriter(networkStream))
{
streamWriter.WriteLine(data);
}
}
The issue was the using block around StreamWriter, removing it allowed the underlying stream to continue.
I'm creating one file and sending that file through mail, while
sending Mail I'm getting this error, can you suggest what to send
mails?
kindly tell me where to add code to stop coming warning of "it is
bieng userd by another process"
protected void btnMail_Click(object sender, EventArgs e)
{
Response.Clear();
FileStream fStream = File.Create(strPath); at this line its jumping to catch block
Response.Clear();
try
{
if (Session["Projectname"] != null && Session["Projectname"].ToString() != string.Empty)
{
string Projname = Session["Projectname"].ToString();
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
design.RenderControl(htmlWrite);
string strBuilder = stringWrite.ToString();
string strPath = Request.PhysicalApplicationPath + "\\Temp\\WeeklyReport of " + Projname + ".doc";
LblNoteMsg.Text = strPath;
if (File.Exists(strPath))
{
File.Delete(strPath);
}
FileStream fStream = File.Create(strPath);
fStream.Close();
fStream.Dispose();
StreamWriter sWriter = new StreamWriter(strPath);
sWriter.Write(strBuilder);
sWriter.Close();
sWriter.Dispose();
Response.Clear();
DateTime input = DateTime.Now;
int delta = DayOfWeek.Monday - input.DayOfWeek;
DateTime dats = DateTime.Now.AddDays(delta);
//this week
DateTime monday = input.AddDays(delta);
string MonDate = monday.ToShortDateString();
DateTime sat = monday.AddDays(5);
string SatDate = sat.ToShortDateString();
StreamReader r = new StreamReader(Server.MapPath("~/WeeklyMail.txt"));
string body = r.ReadToEnd();
MailMessage Msg = new MailMessage();
string MailId = txtMailId.Text;
foreach (string ss in MailId.Split(",".ToCharArray()))
{
if (string.IsNullOrEmpty(ss) == false)
{
Msg.To.Add(new MailAddress(ss));
}
}
Msg.Bcc.Add(new MailAddress("support#sunlightit.com"));
body = body.Replace("<%MonDate%>", MonDate);
body = body.Replace("<%SatDate%>", SatDate);
Msg.Subject = "Weekly status Report of " + Projname + "," + DateTime.Now.ToShortDateString() + "";
Msg.Body = body;
Msg.IsBodyHtml = true;
Msg.Attachments.Add(new Attachment(strPath));
SmtpClient MailServer = new SmtpClient();
try
{
MailServer.Send(Msg);
string reply = (Msg.DeliveryNotificationOptions = System.Net.Mail.DeliveryNotificationOptions.OnSuccess).ToString();
if (reply == "OnSuccess")
{
txtMailId.Text = "";
tblMail.Visible = false;
lblMsg.ForeColor = System.Drawing.Color.Green;
lblMsg.Text = "Mail has send succesfully";
}
else
{
lblMsg.ForeColor = System.Drawing.Color.Red;
lblMsg.Text = "Mail delivery unsuccessfull";
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
if (ex.InnerException != null)
{
Console.WriteLine("InnerException is: {0}", ex.InnerException);
}
}
}
else
{
Response.Redirect("~/Login.aspx");
}
}
catch (Exception)
{
ScriptManager.RegisterClientScriptBlock(Page, typeof(Page), "clentscript", "alert('It is being used by another process.Please Try after sometime ');", true);
}
}
from this line its going to catch block .file is not creating
FileStream fStream = File.Create(strPath);
looking at your code, you don't need to do the calls to .dispose() as this is what the using block is for, so you could have:
using (var fStream = File.Create(strPath).Close())
{
// these can go - (arguable you dont even need to do the close above,
// but it's there for completeness's sake)
//fStream.Close();
//fStream.Dispose();
}
using(StreamWriter sWriter = new StreamWriter(strPath))
{
sWriter.Write(strBuilder);
sWriter.Close();
//sWriter.Dispose(); - this can go too
Response.Clear();
}
Furthermore, you should probably use a similar approach to the bit where you use the StreamReader.
Also - strPath will end up hanging around on the file system (is this desirable?)
If you're merely wanting to ensure unique file names you could just use a Path.GetRandomFilename() (see this MSDN article)
Finally, I'd look into pulling some of this (esp the "unique file name" bit) into extension methods or testable helper objects.
HTH!
Andy
Have you checked the directory?
string strPath = Request.PhysicalApplicationPath + "\Temp\WeeklyReport of " + Projname + ".doc";
if(Directory.Exists("...\Temp"))
{
}
complete guess - but I suspect you're running into a process maintaining a file lock that hasn't disposed from previous calls (i.e the fileStream is opened on create on the first time around, leaving a lock floating about and then on subsequent calls trying to create the file again)
If it was me: I'd change this bit to use File.WriteAllLines() (which creates the file/ overwrites the existing file, writes, closes and disposes all in one hit)
Check : File.WriteAllLines on MSDN
Good luck!
OR
Even better - why create files at all? If you're only using them to attach to the mail, why don't you just write the contents into a memorystream and base the attachment around that stream (after you've rewound it).
Here's a link to the attachment CTor you'll need on MSDN
Code example:
System.Net.Mail.Attachment attachment = null;
using (var ms = new System.IO.MemoryStream())
{
using (var sw = new System.IO.StreamWriter(ms))
{
sw.Write("contents here");
sw.Flush();
}
ms.Position = 0;
attachment = new System.Net.Mail.Attachment(ms, "FileNameHere.txt");
}
var msg = new System.Net.Mail.MailMessage()
{
Body = "body text here",
Subject = "some subject"
};
msg.Attachments.Add(attachment);
PS - I note from your code that you're not deleting the file after sending anywhere - might want to consider that.
Sending XML from C# Server and receiving it it in Android Java client
This is what the received XML look likes:
<?xml version="1.0" encoding="utf-8"?>.....
This is the c# send code
// convert the class WorkItem to xml
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(typeof(WorkItem));
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
xs.Serialize(xmlTextWriter, p);
// send the xml version of WorkItem to client
byte[] data = memoryStream.ToArray();
clientStream.Write(data, 0, data.Length);
Console.WriteLine(" send.." + data);
clientStream.Close();
In Java i just do:
in = new DataInputStream(skt.getInputStream());
String XMlString = in.readLine();
Everything is working if i every time remove the 3 first characters from XMlString.
I would really like to do this in a better way if it's possible
*UPDATE adding the Android java client
#Override
protected String doInBackground(Long... params) {
textTopInfo.setText("Loading workitems..");
DataOutputStream out = null;
DataInputStream in = null;
try {
Socket skt = new Socket(Consts.SERVER_URL_1, Consts.SERVER_PORT_1);
skt.setSoTimeout(10000); //10 sec timout
out = new DataOutputStream(skt.getOutputStream());
in = new DataInputStream(skt.getInputStream());
// check valid user id
String id = prefs.getString("id", "");
if(id.equals(""))
return "Open menu and enter User Id";
String theString = Consts.PUSH_GET_WORKITEM + ":" + id ;
out.write(theString.getBytes());
BufferedReader d = new BufferedReader
(new InputStreamReader(skt.getInputStream()));
String XMlString = d.readLine();
// here I remove the BOM
XMlString = XMlString.substring(3);
Log.d(TAG, "GF");
XStream xstream = new XStream();
xstream.alias("WorkItem", WorkItem.class);
xstream.alias("OneItem", OneItem.class);
pl = (WorkItem)xstream.fromXML(XMlString);
} catch (Exception e) {
return "cannot connect to server " + e.toString();
}finally{
//kill out/in
try {
if(out != null)
out.close();
if(in!=null)
in.close();
} catch (IOException e) {
}
}
return "here is the list";
}
the method readLine is deprecated in Java 1.7; from the javadocs:
readLine()
Deprecated.
This method does not properly convert bytes to characters. As of JDK 1.1, the preferred way to read lines of text is via the BufferedReader.readLine() method. Programs that use the DataInputStream class to read lines can be converted to use the BufferedReader class by replacing code of the form:
DataInputStream d = new DataInputStream(in);
with:
BufferedReader d
= new BufferedReader(new InputStreamReader(in));
The three initial bytes is the UTF8 BOM (Byte ordering mark). You will need to tell your Java code to use the same encoding.
I've been stuck with this problem for a few hours and can't seem to figure it out, so I'm asking here :)
Alright, I've got this function:
private void XmlDump()
{
XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
XElement rootElement = new XElement("dump");
rootElement.Add(TableToX("Support"));
string connectionString = ConfigurationManager.ConnectionStrings["MyDb"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
string sql = "select * from support";
SqlDataAdapter da = new SqlDataAdapter(sql, con);
DataSet ds = new DataSet("Test");
da.Fill(ds, "support");
// Convert dataset to XML here
var docresult = // Converted XML
Response.Write(docResult);
Response.ContentType = "text/xml; charset=utf-8";
Response.AddHeader("Content-Disposition", "attachment; filename=test.xml");
Response.End();
}
I've been trying all kind of different things but I keep getting errors, so I've left the how to convert DataSet to XML part blank.
And another thing, this query contains columns with special characters.
You can use ds.WriteXml, but that will require you to have a Stream to put the output into. If you want the output in a string, try this extension method:
public static class Extensions
{
public static string ToXml(this DataSet ds)
{
using (var memoryStream = new MemoryStream())
{
using (TextWriter streamWriter = new StreamWriter(memoryStream))
{
var xmlSerializer = new XmlSerializer(typeof(DataSet));
xmlSerializer.Serialize(streamWriter, ds);
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
}
}
}
USAGE:
var xmlString = ds.ToXml();
// OR
Response.Write(ds.ToXml());
Simply use Dataset.getXml():
doc.LoadXml(ds.GetXml());
Write like below code part
DataTable dt = new DataTable("MyData");
dt.WriteXml(#Application.StartupPath + "\\DataBaseValues.xml");
Or, You can convert directly the dataSet also as said by Oded like,
private void WriteXmlToFile(DataSet thisDataSet)
{
if (thisDataSet == null)
{
return;
}
// Create a file name to write to.
string filename = "myXmlDoc.xml";
// Create the FileStream to write with.
System.IO.FileStream myFileStream = new System.IO.FileStream(filename, System.IO.FileMode.Create);
// Create an XmlTextWriter with the fileStream.
System.Xml.XmlTextWriter myXmlWriter =
new System.Xml.XmlTextWriter(myFileStream, System.Text.Encoding.Unicode);
// Write to the file with the WriteXml method.
thisDataSet.WriteXml(myXmlWriter);
myXmlWriter.Close();
}
Use DataSet.WriteXml - it will output the dataset as XML.
if ds is your dataset..
you can use:
ds.getXml();
this helps in getting XML
We can use this also
Private Function DsToXML(DataSet ds) as System.Xml.XmlDataDocument
Dim xmlDoc As System.Xml.XmlDataDocument
Dim xmlDec As System.Xml.XmlDeclaration
Dim xmlWriter As System.Xml.XmlWriter
xmlWriter = New XmlTextWriter(context.Response.OutputStream,System.Text.Encoding.UTF8)
xmlDoc = New System.Xml.XmlDataDocument(ds)
xmlDoc.DataSet.EnforceConstraints = False
xmlDec = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", Nothing)
xmlDoc.PrependChild(xmlDec)
xmlDoc.WriteTo(xmlWriter)
Retuen xmlDoc
End Eunction
Try this. It worked for me.
static XmlDocument xdoc = new XmlDocument(); //static; since i had to access this file someother place too
protected void CreateXmlFile(DataSet ds)
{
//ds contains sales details in this code; i.e list of products along with quantity and unit
//You may change attribute acc to your needs ; i.e employee details in the below code
string salemastid = lbl_salemastid.Text;
int i = 0, j=0;
String str = "salemastid:" + salemastid;
DataTable dt = ds.Tables[0];
string xml = "<Orders>" ;
while (j < dt.Rows.Count)
{
int slno = j + 1;
string sl = slno.ToString();
xml += "<SlNo>" + sl +"</SlNo>" +
"<PdtName>" + dt.Rows[j][0].ToString() + "</PdtName>" +
"<Unit>" + dt.Rows[j][1].ToString() + "</Unit>" +
"<Qty>" + dt.Rows[j][2].ToString() + "</Qty>";
j++;
}
xml += "</Orders>";
xdoc.LoadXml(xml);
//Here the xml is prepared and loaded in xml DOM.
xdoc.Save(Server.MapPath("Newsales.xml"));
//You may also use some other names instead of 'Newsales.xml'
//to get a downloadable file use the below code
System.IO.MemoryStream stream = new System.IO.MemoryStream();
XmlTextWriter xwriter = new XmlTextWriter(stream, System.Text.Encoding.UTF8);
xdoc.WriteTo(xwriter);
xwriter.Flush();
Response.Clear();
Encoding.UTF8.GetString(stream.ToArray());
byte[] byteArray = stream.ToArray();
Response.AppendHeader("Content-Disposition", "filename=OrderRequest.xml");
Response.AppendHeader("Content-Length", byteArray.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.BinaryWrite(byteArray);
xwriter.Close();
stream.Close();
}
I have stored an excel file in my SQL Server 2008 DB (as a VARBINARY(MAX)) the following (so far, hard coded) way:
// C# - visual studio 2008
var update = new SqlCommand("UPDATE Requests SET Attachment = #xls" +
" WHERE RequestsID = 27", conn);
update.Parameters.AddWithValue("xls", File.ReadAllBytes("C:/aFolder/hello.xlsx"));
update.ExecuteNonQuery();
It works, but I want to open it too!
How do I do that?
Note, not read blob-data, but open the actual "hello.xlsx" file.
I have tried the following:
http://dotnetsoldier.blogspot.com/2007/07/how-to-retrieve-blob-object-in-winforms.html
I can see it works, as "Binary.Length" is exactly the size of my "hello.xlsx" when executing - but the file doesn´t open, and that´s my problem.
Please help me out!
EDIT:
HERE IS THE CODE THAT I CURRENTLY USE TO "OPEN" THE SPREADSHEET:
SqlConnection conn =
new SqlConnection
(global::MY_PROJECT.Properties.Settings.Default.DB_1ConnectionString);
conn.Open();
SqlCommand Cmd = new SqlCommand("select Attachment from Requests where RequestsID = 27", conn);
Cmd.CommandType = CommandType.Text;
SqlDataReader Reader = Cmd.ExecuteReader(CommandBehavior.CloseConnection);
//
string DocumentName = null;
FileStream FStream = null;
BinaryWriter BWriter = null;
//
//
//
byte[] Binary = null;
const int ChunkSize = 100;
int SizeToWrite = 0;
MemoryStream MStream = null;
//
while (Reader.Read())
{
DocumentName = Reader["Attachment"].ToString();
// Create a file to hold the output.
FStream = new FileStream(#"c:\" + DocumentName, FileMode.OpenOrCreate, FileAccess.Write);
BWriter = new BinaryWriter(FStream);
Binary = (Reader["Attachment"]) as byte[];
SizeToWrite = ChunkSize;
MStream = new MemoryStream(Binary);
//
for (int i = 0; i < Binary.GetUpperBound(0) - 1; i = i + ChunkSize)
{
if (i + ChunkSize >= Binary.Length) SizeToWrite = Binary.Length - i;
byte[] Chunk = new byte[SizeToWrite];
MStream.Read(Chunk, 0, SizeToWrite);
BWriter.Write(Chunk);
BWriter.Flush();
}
BWriter.Close();
FStream.Close();
}
FStream.Dispose();
conn.Close();
The code you posted looks like it probably writes the spreadsheet to disc but I can't see any code to open it. You would need to use something like
System.Diagnostics.Process.Start(#"c:\" + DocumentName)
I think.