I have successfully used Axis 1.1 Final to create the web service and used
the .NET 1.1 with WSE 1.0 SP1 for the client side.
This is a simple web service that sends as DIME attachment the file whose
name is provided in the input.
The code for server side is as follows:
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////
package com.its.portfolioip.services;
import javax.xml.soap.AttachmentPart;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.attachments.Attachments;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.InputStream;
import java.rmi.RemoteException;
import org.apache.log4j.Category;
public class FileService {
private static Category log = Category.getInstance(FileService.class);
public String GetFile(String filename)
throws RemoteException {
log.info("Retrieving file:" + filename);
// Lookup the file required
log.debug("Loading the file " + filename + " to send the response.");
InputStream stream;
try {
stream = new FileInputStream(filename);
}
catch (IOException ioe) {
log.error(ioe);
log.debug("Error occurred while loading file " + filename);
throw new RemoteException(ioe.toString());
}
// Set the file as attachment
log.debug("Sending the File " + filename + " as attachment");
try {
MessageContext ctx = MessageContext.getCurrentContext();
Message m = ctx.getResponseMessage();
Attachments ats = m.getAttachmentsImpl();
ats.setSendType(Attachments.SEND_TYPE_DIME);
// Axis says that it always returns an AttachmentPart
// TODO : catch ClassCastException to be sure
AttachmentPart ap = (AttachmentPart)
ats.createAttachmentPart();
// Earlier the attachment part was created using message but
it does not
provide API for setting send type as DIME
// AttachmentPart ap = m.createAttachmentPart();
ap.setContent(stream, null);
m.addAttachmentPart(ap);
}
catch (Exception e) {
log.error(e);
log.debug("Error occurred while attaching file " + filename);
throw new RemoteException(e.toString());
}
log.info("Ready to send file " + filename);
return filename;
}
}
////////////////////////////////////////////////////////////////////////////
/////////////////
On the client side, use Visual studio to generate the proxy. Add
Microsoft.Web.Services.dll in the references and manually change the
superclass of proxy. The automatically generated proxy is derived from
System.Web.Services.Protocols.SoapHttpClientProtocol. Change it to
Microsoft.Web.Services.WebServicesClientProtocol. Your proxy would be
public class FileServiceService :
Microsoft.Web.Services.WebServicesClientProtocol {...
...
}
The client side code which uses the proxy looks as follows. It simply copies
the file to another file.
////////////////////////////////////////////////////////////////////////////
////////////////
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using AttachmentTest.localhost;
using System.IO;
using System.Web.Services.Protocols;
using Microsoft.Web.Services;
namespace AttachmentTest
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.Button button1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent
call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox2 = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(24, 40);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(248, 20);
this.textBox1.TabIndex = 0;
this.textBox1.Text = @"C:\test.txt";
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(24, 80);
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(248, 20);
this.textBox2.TabIndex = 1;
this.textBox2.Text = @"C:\testCopy.txt";
//
// button1
//
this.button1.Location = new System.Drawing.Point(176, 136);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(96, 24);
this.button1.TabIndex = 2;
this.button1.Text = "button1";
this.button1.Click += new
System.EventHandler(this.button1_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.button1);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e) {
String copyFrom = textBox1.Text;
String copyTo = textBox2.Text;
String serviceUrl =
"http://localhost:8081/portfolioip/services/FileService";
String str = CallFileService(copyFrom, serviceUrl);
try {
FileStream fs = new FileStream(copyTo, FileMode.Create,
FileAccess.Write);
byte[] b = System.Text.Encoding.ASCII.GetBytes(str);
fs.Write(b, 0, b.Length);
fs.Close();
MessageBox.Show("Copied the file successfully");
}
catch (Exception ex) {
MessageBox.Show("Could not copy the file. " +
ex.ToString());
}
}
private String CallFileService(String filename, String serviceUrl) {
FileServiceService proxy = new FileServiceService();
proxy.Url = serviceUrl;
proxy.RequestSoapContext.Path.MustUnderstand = false;
String str = String.Empty;
try {
String result = proxy.GetFile(filename);
}
catch (Exception e) {
str = "<Exception>" + e.Message + "</Exception>";
return str;
}
int n = proxy.ResponseSoapContext.Attachments.Count;
if (n < 1) {
str = "<Exception>No file has been attached by the
FileService.</Exception>";
return str;
}
// Use only the first attachment
try {
StreamReader stream = new
StreamReader(proxy.ResponseSoapContext.Attachments[0].Stream);
str = stream.ReadToEnd();
stream.Close();
}
catch (Exception e) {
str = "<Exception>Could not read the attachment. The
underlying
exception is " +
e.Message +
"</Exception>";
}
return str;
}
}
}
////////////////////////////////////////////////////////////////////////////
/////////////////
>From reading the documentation, it appears that it may be possible now to
run attachments without manually changing the automatically generated proxy.
I will look into that also. Let me know if this helps.
Best regards,
Abhinav Maheshwari
-----Original Message-----
From: Jim Collins [mailto:[EMAIL PROTECTED]
Sent: Tuesday, March 23, 2004 2:16 AM
To: [EMAIL PROTECTED]
Subject: Re: Attachment from Axis service causing .NET to Error
I am using AXIS 1.2 alpha and Tomcat 5.0.3 and a .net application has been
able to access the atachment I send. They were initially having problems
until they installed the Web services enhancements service pack.
Regards
Jim.
----- Original Message -----
From: "sergeant" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Monday, March 22, 2004 3:52 PM
Subject: RE: Attachment from Axis service causing .NET to Error
> Yes, I'm using WSE10SP1. Uploading an attachment works fine, downloading
> from Axis on tomcat 4.1.29 fails with the message indicated below.
>
> Here I'm talking about the HTTP Content-Type header. This must be
> 'application/dime' when sending attachments to a .NET client, rather
> than 'multipart/related'. At least that is my understanding based on
> reading, and viewing SOAP conversations on the wire between .NET
> services and clients. It is also what Axis uses when you set the
> send type like this:
>
> messageAttachments.setSendType(Attachments.SEND_TYPE_DIME);
>
> After tracking this down the only issue I can see is the addition
> of the unnecessary ';charset=ISO-8859-1' by tomcat 1.4.29.
> I could be wrong about this, but it does seem to match the error
> messages and other evidence.
>
> What servlet engine and version are you using?
>
> Thanks for the response.
>
> --Brad
>
> -----Original Message-----
> From: Abhinav Maheshwari [mailto:[EMAIL PROTECTED]
> Sent: Monday, March 22, 2004 4:06 AM
> To: [EMAIL PROTECTED]; [EMAIL PROTECTED]
> Subject: RE: Attachment from Axis service causing .NET to Error
>
>
> Hi Sergeant,
> Do you have the Web Service Enhancements 1.0 with Service Pack 1 installed
> on your Visual Studio ? This is necessary to handle attachments on the
.NET
> client. In my opinion, the problem is not due to charset but the content
> type 'application/dime'.
>
> In case, this does not resolve your problem, I will mail again with
detailed
> steps. Seems like many users are having problems with attachments.
>
> Warm regards,
> Abhinav Maheshwari
>
> -----Original Message-----
> From: sergeant [mailto:[EMAIL PROTECTED]
> Sent: Saturday, March 20, 2004 8:44 AM
> To: [EMAIL PROTECTED]
> Subject: Attachment from Axis service causing .NET to Error
>
>
> BACKGROUND: I'm using Axis 1.1 on Tomcat 4.1.29. I've written a WSDL
using
> a simple document/literal approach and am interoperating with both Axis
and
> .NET clients. I've introduced an operation that returns a binary
attachment
> and this works fine with the Axis client. The WSDL knows nothing of the
> attachment, (using the approach suggested by the Axis attachment FAQ),
> except that I am using a SOAP Header to indicate whether to use DIME or
not.
>
> PROBLEM: The C# .NET client fails with the following error message when it
> receives the response:
> "Client found response content type of
> 'application/dime;charset=ISO-8859-1', but expected 'text/xml'."
>
> Using tcpmon I verified that the following was being sent from the
service:
> Content-Type: application/dime;charset=ISO-8859-1
>
> DETAILS: It appears to me that the addition of the ";charset=ISO-8859-1"
is
> causing the problem. Monitoring communication between .NET client/Server
> shows they expect just "application/dime" and no charset. From the
> AxisServlet code it is clear to me that Axis is doing the right thing.
The
> problem is that Tomcat is forcing the ";charset=..." to be added when
> HttpServletResponse.setContentType() is called. I have been able to
change
> it to "application/dime;charset=utf-8", but that did not fix the interop
> problem.
>
> QUESTION: Anyone run into this? Anyone using a different version of
Tomcat
> or another Servlet engine that they know avoids this problem?
>
> CHOICES: My next path is to either get a different servlet engine or to
> download the source to Tomcat and fix it myself. Any other suggestions?
>
> Thanks for any help.
>
> --Brad Sergeant
>
> SIDE COMMENT: I've been enjoying using Axis and feel the development
> environment is efficient, using Ant to generate the client and server
stubs,
> compile, deploy, and reload axis makes turnaround very fast. Trick seems
to
> be to get the WSDL right for interop.
>
>