简体   繁体   中英

Return XML From Web Api

I've done hours of reading on this and tried many different solutions I've found on SO and else where and still haven't been able to get this working.

The situation is, I've written a web api rest service to provide an interface to a 3rd party application via COM. It's been in production now for a number of months and works flawless. I've been tasked by a new consumer to provide XML responses, up until now it's been working exclusively with JSON perfectly fine. No matter what I try I can not get an XML response using Postman for testing. In Post man I have both the content-type and accept header tags set to "application/xml"

So my controller is pretty simple

public class SampleController : ApiController
{
    [HttpGet]
    [Route("api/getobject")]
    public HttpResponseMessage GetByGSTNumber(string token, string key)
    {
        DataConnection connection = null; new DataConnection();//Set up COM reference
        DataObject dataObj = null;
        try
        {
            connection = new DataConnection();
            connection.login(token);
            dataObj = new DataObject(connection);
            Request.CreateResponse(HttpStatusCode.OK, dataObj);
        }
        catch (Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
        }
        finally
        {
            if (connection != null) { Request.RegisterForDispose(connection); }
            if (dataObj != null) { Request.RegisterForDispose(dataObj); }
        }
    }
}

The Definition of my data object, again don't think overly complicated. It does do a bit of parsing under the hood to convert non CLR types to CLR types.

public class DataObject : IDisposable
{
    internal DataConnection dbConnection;
    internal dynamic _dataRecord;
    public string Key
    {
        get { return _dataRecord.KeyField.ToString(); }
    }

    public string Property1
    {
        get { return _dataRecord.Property1Feild.ToString(); }
    }

    public DataObject(DataConnection connection)
    {
        dbConnection = connection;
    }

    public void OpenRecord(string key)
    {
        if (!_dataRecord.Seek(key))
        {
            throw new Exception("Record not found");
        }

    }

    #region IDisposable Support
}

So what I've tried so far is change

return Request.CreateResponse(HttpStatusCode.OK, dataObj);
//Returns JSON even if specifying XML in request

to

return Request.CreateResponse(HttpStatusCode.OK, dataObj "application/xml");
// returns <ExceptionMessage>Could not find a formatter matching the media type 'application/xml' that can write an instance of 'DataObject'.</ExceptionMessage>

I've decorated my data object with [DataContract] and properties with [DataMember] tags but that resulted in no change.

I've created a parameterless constructor, which got me this, but no properties/values are in the xml

I've tried setting the XML Serializer in my Global.asax file but this had no noticeable effect. What am I missing?

Update Included application start where I've tried different combos of UseXMLSerializer = true/false with all the above changes

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
        xml.UseXmlSerializer = true;
    }

I've also tried putting an XML serialize method on my data object and changing my create response call

public string XMLSerialize()
    {
        XmlSerializer xsSubmit = new XmlSerializer(typeof(DataObject));
        using (var sww = new StringWriter())
        {
            using (XmlWriter writer = XmlWriter.Create(sww))
            {
                xsSubmit.Serialize(writer, this);
                return sww.ToString(); // Your XML
            }
        }
    }

return Request.CreateResponse(HttpStatusCode.OK, creditor.XMLSerialize(), "application/xml");

This results in a There was an error generating the XML document. System.InvalidOperationException Exception aside, I'm not 100% sure that this would produce a correctly formatted result

Update Have changed the properties on my business class to have an empty setter and now getting XML with properties in my response. Visual studio is complaining about empty setters but compiling, I'm guessing it's not the norm.

    public string Key
    {
        get { return _dataRecord.KeyField.ToString(); }
        set {} VS give me a wiggly green line on this but no info
    } 

For all those that helped. Thanks a ton. Credit goes to Steve16351 for giving me the hint that got me going in the right direction.

So the problem was in the way I had defined my DataObject class. I needed two changes.

Firstly a paramaterless constructor. Secondly, I needed to specify property setters. Initially didn't think I needed setters since I would never need to Post data using this class as it's underlying data source is read only.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM