views:

108

answers:

4

I need advice on how to return a limited set of data from an MVC controller.

Lets say I have a class that is constructed like so:

public interface ICustomerExpose
{
   string Name {get; set;}
   string State {get; set;}
}

public interface ICustomer: ICustomerExpose
{
   int Id {get; set;}
   string SSN {get; set;}
}

public class Customer: ICustomer
{
   ...
}

In my MVC project I have a controller action that returns customer data. The project is actually more like a web service as there is no View associated with the data... we use the XmlResult (provided by the MVCContrib project). The controller action looks like this:

    // GET: /Customer/Show/5
    public ActionResult Show(int id)
    {
        Customer customer = Customer.Load(id);

        ...  // some validation work

        return new XmlResult((ICustomerExpose)customer);
    }

The above controller code does not work like I want it to. What I want to happen is that only the Name and State properties are serialized and returned in the XmlResult. In practice the whole customer object is serialized including the data I definitely don't want exposed.

I know the reason this doesn't work: you can't serialize an interface.

One idea floated around the office was to simply mark the properties Name and State as [XmlIgnore]. However, this doesn't seem like a good solution to me. There might be other instances where I want to serialize those properties and marking the properties on the class this way prohibits me.

What is the best way to achieve my goal of only serializing the properties in the ICustomerExpose interface?

Addendum:

For those interested in what XmlResult does here are the relevant parts of it:

 public class XmlResult : ActionResult
 {
     private object _objectToSerialize;
     public XmlResult(object objectToSerialize)
     {
        _objectToSerialize = objectToSerialize;
     }

     /// <summary>
     /// Serialises the object that was passed into the constructor 
     /// to XML and writes the corresponding XML to the result stream.
     /// </summary>
     public override void ExecuteResult(ControllerContext context)
     {
         if (_objectToSerialize != null)
         {
            var xs = new XmlSerializer(_objectToSerialize.GetType());
            context.HttpContext.Response.ContentType = "text/xml";
            xs.Serialize(context.HttpContext.Response.Output, _objectToSerialize);
         }
     }
 }
A: 

You can try this, however I am not sure if it works with xml serializers:

return new XmlResult(new { customer.Name, customer.State });
Andrey Shchekin
Unfortunately this doesn't work. Anonymous methods cannot be serialized because they doesn't have a parameterless constructor (according to the error message generated by the XmlSerializer).
Sailing Judo
A: 

See this related question which recommends using an anonymous type.

// GET: /Customer/Show/5
public ActionResult Show(int id)
{
    Customer customer = Customer.Load(id);

    ...  // some validation work

    var result = from c in cusomter
                 select new
                 {
                     Name = c.Name,
                     State = c.State,
                 };

    // or just

    var result = new
                 {
                     Name = customer.Name,
                     State = customer.State,
                 };


    return new XmlResult(result);
}
Todd Smith
Unfortunately this doesn't work. Anonymous methods cannot be serialized because they doesn't have a parameterless constructor (according to the error message generated by the XmlSerializer).
Sailing Judo
A: 

Consider using, just for this one problem, XML literals in VB9 rather than serialization. Seriously. Just give it 20 minutes of your time. There's many options.

http://www.hanselman.com/blog/TheWeeklySourceCode30VBNETWithXMLLiteralsAsAViewEngineForASPNETMVC.aspx

http://www.hanselman.com/blog/XLINQToXMLSupportInVB9.aspx

http://blogs.msdn.com/dmitryr/archive/2008/12/29/asp-net-mvc-view-engine-using-vb-net-xml-literals.aspx

http://haacked.com/archive/2008/12/29/interesting-use-of-xml-literals-as-a-view-engine.aspx

http://www.infoq.com/news/2009/02/MVC-VB

For what you're doing, returning XML as a poor-man's Web Service, this is tailor-made.

Scott Hanselman
A: 

I ended up just doing the XmlIgnore as co-workers suggested, even though this left me with some undesirable (or so I thought) behaviors.

To get around the fact that XmlIgnore would continue hiding properties that I might want serialized later I asked another question trying to find a way to around that issue. Cheeso came up with a great answer making the XmlIgnore the best route (in my opinion) to take.

Sailing Judo