Frage

Ich habe Folgendes:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(SportProgram))]
[ServiceKnownType(typeof(ActionResult<SportProgram>))]
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

Wenn ich die GET -Methode ausführe, erhalte ich den folgenden Fehler:

Es gab einen Fehler beim Versuch, Parameter zu serialisieren http://tempuri.org/:getresult. Die Innerexception -Nachricht war 'type' pps.core.domainmodel.support.action.actionresult`1 [[pps.core.domainmodel NULL]] 'mit Datenvertragsname' ActionResultofanytype: http://schemas.datacontract.org/2004/07/pps.core.domainmodel.support.action'ist nicht erwartet. Fügen Sie der Liste der bekannten Typen, beispielsweise durch die Verwendung des Attributs bekannter TypeatTribute oder durch Hinzufügen zu der Liste der an DataContractribute -Attribut hinzugefügten Typen hinzu. Weitere Informationen finden Sie in Innerexception.

Aus diesem Fehler kann ich feststellen, dass es ActionResult beheben kann, aber ISPSOGROGRAM nicht beheben kann, obwohl ich habe ServiceBousNtype (typeof (actionResult <SPORTROGRAM>)) Auf meiner Service -Oberfläche ...

Beachten Sie, dass dies der erzeugte Referenzstub ist, sodass ich sehen kann, dass die bekannten Typen korrekt zur Verfügung gestellt werden:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SportProgramStb.ISportProgramBl")]
public interface ISportProgramBl {

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISportProgramBl/Get", ReplyAction="http://tempuri.org/ISportProgramBl/GetResponse")]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.SportProgram.SportProgram))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionParameters))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionResult<PPS.Core.DomainModel.SportProgram.SportProgram>))]
    object Get(object parameters);
}

Warum läuft das schief ???? Beachten Sie, dass es den WCF -Dienst korrekt durchläuft ... aber es macht die Ausnahme, wenn das Ergebnis zurückgegeben wird.

Zuletzt sieht ActionResult so aus:

public interface IActionResult<T> 
{
    T Result { get; set; } 
}

Prost Anthony

War es hilfreich?

Lösung

Nun, ich denke, dies ist ein weiterer Fall der SOA vs. OOP "Impedanz -Nichtübereinstimmung". Die beiden Welt sind ziemlich getrennt.

In WCF wird alles, was vom Client an den Server übergeben wird Serialisierte Nachrichten - Es werden keine Referenzen verwendet.

Dies bedeutet: Alles, was Sie auf dem Client serialisieren möchten, senden Sie ihn an den Server und deserialisieren es und verwenden Sie es dort, muss es sein, muss sein Beton - Sie können nicht um Schnittstellen vorbeikommen, Sie können nicht aufgelöste Generika "nicht aufgelöste" verwenden - Sie müssen es ausschreiben. Grundsätzlich muss im XML -Schema nur alles, was vom Client über das Kabel zum Server übergeben wird.

Dies hat viele Auswirkungen:

  • Keine Schnittstellen - Sie können nicht um Schnittstellen vorbeikommen - Sie müssen mit Betontypen arbeiten
  • Keine "automatische" Vererbung - Sie können nicht einfach eine Basisklasse definieren und abgeleitete Klassen basierend darauf bestehen - diese müssen auch spezifisch sein (dafür ist das Attribut "Service -KnospeNType")
  • Keine automatischen Generika - Auch hier müssen Sie stattdessen Betontypen verwenden

Dies mag nach vielen Einschränkungen klingen - aber weil WCF alle meldungsbasierte Kommunikation verwendet - kann es nicht mit Referen, Vererbung, Generika usw. umgehen - Sie müssen sie herausfordern.

Ich habe also nicht wirklich eine Antwort für Sie per se - ich denke nur, dass Sie Ihre Strategie überdenken und die Art und Weise ändern müssen, wie Ihr Client und Server Informationen über WCF austauschen.

Marc

PS: Ich habe noch einige Nachforschungen angestellt und im Gegensatz zu meinem Verständnis scheint es eine Möglichkeit zu geben, alles zu serialisieren, was auf einer Schnittstelle und/oder einer abstrakten Basisklasse über den Draht basiert, solange Sie sicher sein können, dass es immer nur ist. Netz an beiden Enden des Drahtes (dh es ist es nicht Interoperabel mit EG Java).

Sehen Aaron Skonnard Blog -Beitrag auf dem NetDatacontractSerializer und ein anderer Blogeintrag und noch ein anderer Zeigen, wie man den NetDatacontractSerializer verwendet, um Dinge wie wie IPerson als Parameter zu Ihren Methoden.

Andere Tipps

Dies ist eines der Probleme, mit denen ich löste Servicestack.net - Mein Open Source .NET- und Mono Web Services Framework.

Service -Stack wurde stark von beeinflusst von Martin Fowlers Datenübertragungsobjektmuster Da Sie es mit DTOs einfach verwenden können, um Ihre Webdienste zu definieren - dh die SOA -Art :).

Ich vermeide diese Einschränkung, die WCF inhärent ist, indem ich meine eigenen WSDLs generiere, die sich so verhalten, wie Sie es erwarten würden. Als Vorteil des Ersetzens des Komplexen Konfigurations- / ServicEContract -Modells von WCF - die SOAP -Webdienste funktionieren auch auf Mono - Siehe die Live -Demo.

Es ist eine alte Frage, und obwohl die akzeptierte Antwort völlig korrekt ist, bin ich auf der Suche nach einem ähnlichen Problem darauf gestoßen und dachte, ich könnte meine Erfahrungen teilen. Es ist oft Kopfschmerzen, aber es ist möglich, Generika in Kombination mit Schnittstellen mit WCF zu verwenden. Hier ist ein funktionierendes Beispiel für eine andere (ähnliche) Implementierung, die ich durchgeführt habe:

[ServiceContract]
[ServiceKnownType(typeof(CollectionWrapper<IAssociation>))]
public interface IService : 
{
    [OperationContract]
    ICollectionWrapper<IAssociation> FindAssociation(string name, int pageSize, int page);
}

public interface ICollectionWrapper<TModel>
{
    int TotalCount { get; set; }
    IEnumerable<TModel> Items { get; set; }
}

[KnownType(typeof(OrganizationDto))]
[KnownType(typeof(CompanyDto))]
public class CollectionWrapper<TModel> : ICollectionWrapper<TModel>
{
    [DataMember]
    public int TotalCount { get; set; }
    [DataMember]
    public IEnumerable<TModel> Items { get; set; }
}

public class CompanyDto :  IAssociation
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class OrganizationDto :  IAssociation
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Der Schlüssel hier ist die Verwendung der Kombination von KnownType und ServiceKnownType.

In Ihrem Fall können Sie also so etwas tun:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(ActionResult<ISportProgram>))] // Actual implementation of container, but interface of generic.
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

[KnownType(typeof(SportProgram))] // Actual implementation here.
public class ActionResult<T>
{
    // Other stuff here
    T FooModel { get; set; }
}

Dies funktioniert, wenn Sie einen gemeinsamen Vertrag haben (Zugriff auf die tatsächliche Serviceschnittstelle) und den Vertrag mit konsumieren ChannelFactory<ISportProgramBl>. Ich weiß nicht, ob es mit einer Service-Referenz funktioniert.

Es scheint jedoch einige Probleme mit der hier erwähnten Umsetzung zu geben:

WCF mit einer Schnittstelle und einem generischen Modell

Und eine weitere ähnliche Frage, die hier gestellt und beantwortet wurde:

Generische Rückgabetypen mit Schnittstellentypparameten in WCF

Sie erwidern einen Ilist von T. Es ist vielleicht, dass das System Probleme hat, herauszufinden, was T ist.

Ich bin mir nicht sicher, ob es in Ordnung ist, eine Schnittstelle und nicht einen Typ zurückzugeben.

Fassen Sie Schnittstellen in den Objekten und nicht in konkreten Typen an?

PPS.Core.DomainModel.Support.Action.ActionListResult<IList<PPS.Core.DomainModel.SportProgram.ISportProgram>>

Bearbeiten:

Ich sage, dass es sich um alle konkreten Typen handelt, die Sie in den Generika (einschließlich des Sub -Objekts über Schnittstellen) übergeben werden, die in die Liste der bekannten Typen übergeben werden. Wir hatten Serialasationsprobleme, bei denen nicht alle Typen bekannt waren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top