Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I serialize an anonymous object for sending over a SOAP web service?

I am trying to send an anonymous object over a web service. Is there anyway I can do this without manually creating a class and casting it to that class? Currently its throwing an exception saying Anonymous object could not be serialized.

// Some code has been removed here to simplify the example.
[WebMethod(EnableSession = true)]
public Response GetPatientList() {
    var patientList = from patient in ((User)Session["user"]).Practice.Patients
                      select new {
                          patientID = patient.PatientID,
                          status = patient.Active ? "Active" : "Inactive",
                          patientIdentifier = patient.PatientIdentifier,
                          physician = (patient.Physician.FirstName + " " + patient.Physician.LastName).Trim(),
                          lastModified = patient.Visits.Max(v => v.VisitDate)
                      };
    return patientList;
}

Thanks in advance.

Edit: Here is an example of what I mean by manually creating a class to return and fill it with the anonymous object...

public class Result {
    public bool success;
    public bool loggedIn;
    public string message;
}

public class PracticeInfoResult : Result {
    public string practiceName;
    public string address;
    public string city;
    public string state;
    public string zipCode;
    public string phone;
    public string fax;
}
like image 928
Shawn Avatar asked Dec 03 '08 14:12

Shawn


People also ask

How do you declare an anonymous object?

Typically, when you use an anonymous type to initialize a variable, you declare the variable as an implicitly typed local variable by using var. The type name cannot be specified in the variable declaration because only the compiler has access to the underlying name of the anonymous type.

Can an object be anonymous?

An anonymous object is basically a value that has been created but has no name. Since they have no name, there's no other way to refer to them beyond the point where they are created. Consequently, they have “expression scope,” meaning they are created, evaluated, and destroyed everything within a single expression.

What is serialization in .NET with example?

For example, you can share an object between different applications by serializing it to the Clipboard. You can serialize an object to a stream, to a disk, to memory, over the network, and so forth. Remoting uses serialization to pass objects "by value" from one computer or application domain to another.


2 Answers

Anonymous type are meant to be used for simple projections of very loosely coupled data, used only within a method. If it makes sense for a web method to return data of a type, it really should be decently encapsulated. In other words, even if you can find a way to return an instance of an anonymous type from a web method, I strongly suggest you don't do it.

I would personally not create the classes with public fields either - use automatically implemented properties instead, so you can safely add more behaviour later if you need to.

Note that after you've created the "proper" type, your query expression only needs to change very, very slightly - just add the name of the type between new and { to use an object initializer.

like image 106
Jon Skeet Avatar answered Nov 15 '22 00:11

Jon Skeet


Here is the code I wound up using.

[WebMethod(EnableSession = true)]
public PatientsResult GetPatientList(bool returnInactivePatients) {
    if (!IsLoggedIn()) {
        return new PatientsResult() {
            Success = false,
            LoggedIn = false,
            Message = "Not logged in"
        };
    }
    Func<IEnumerable<PatientResult>, IEnumerable<PatientResult>> filterActive = 
        patientList => returnInactivePatients ? patientList : patientList.Where(p => p.Status == "Active");
    User u = (User)Session["user"];
    return new PatientsResult() {
        Success = true,
        LoggedIn = true,
        Message = "",
        Patients = filterActive((from p in u.Practice.Patients
                      select new PatientResult() {
                          PhysicianID = p.PhysicianID,
                          Status = p.Active ? "Active" : "Inactive",
                          PatientIdentifier = p.PatientIdentifier,
                          PatientID = p.PatientID,
                          LastVisit = p.Visits.Count > 0 ? p.Visits.Max(v => v.VisitDate).ToShortDateString() : "",
                          Physician = (p.Physician == null ? "" : p.Physician.FirstName + " " + p.Physician == null ? "" : p.Physician.LastName).Trim(),
                      })).ToList<PatientResult>()
    };
}
public class Result {
    public bool Success { get; set; }
    public bool LoggedIn { get; set; }
    public string Message { get; set; }
}
public class PatientsResult : Result {
    public List<PatientResult> Patients { get; set; }
}
public class PatientResult  {
    public int PatientID { get; set; }
    public string Status { get; set; }
    public string PatientIdentifier { get; set; }
    public string Physician { get; set; }
    public int? PhysicianID {get;set;}
    public string LastVisit { get; set; }
}

}

like image 41
Shawn Avatar answered Nov 15 '22 00:11

Shawn