2008-12-03 13 views
5

Estoy tratando de enviar un objeto anónimo a través de un servicio web. ¿Hay alguna forma en que pueda hacer esto sin crear manualmente una clase y enviarla a esa clase? Actualmente lanza una excepción que dice que el objeto anónimo no se pudo serializar.¿Cómo serializo un objeto anónimo para enviarlo a través de un servicio web SOAP?

// 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; 
} 

Gracias de antemano.

Editar: Este es un ejemplo de lo que quiero decir con la creación manual de una clase para volver y llenarlo con el objeto anónimo ...

tipo
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; 
} 

Respuesta

7

Anonymous están destinados a ser utilizados para las proyecciones simples de datos muy débilmente acoplados, usados ​​solo dentro de un método. Si tiene sentido que un método web devuelva datos de un tipo, realmente debería estar encapsulado decentemente. En otras palabras, incluso si puede encontrar una forma de devolver una instancia de un tipo anónimo desde un método web, le sugiero encarecidamente que no lo haga.

Yo personalmente no crear las clases con campos públicos, ya sea - utilizar las propiedades implementadas automáticamente en su lugar, para que pueda agregar de forma segura un comportamiento más tarde si es necesario.

Tenga en cuenta que después de haber creado el tipo "adecuado", su expresión de consulta solo necesita cambiar muy, muy levemente, simplemente agregue el nombre del tipo entre new y { para usar un inicializador de objetos.

+0

Sólo por curiosidad, ¿por qué prefiere implementar automáticamente las propiedades sobre los campos públicos? Ver – Kevin

+0

http://csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx –

+0

Si devuelve un mensaje serializado como JSON, no sería eso significa que estás de acuerdo con la idea de que se acopla libremente? esto todavía parece un caso de uso válido. – pc1oad1etter

1

Aquí está el código que terminé usando.

[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; } 
} 

}

Cuestiones relacionadas