私はそうではないと確信していますが、この質問がすでに尋ねられている場合はお詫び申し上げます。これがばかげた質問である場合は、さらにお詫び申し上げますが、何かが完全に欠けているか、正しい考えを持っていて、自分の正気のためにバックアップが必要なように感じます。
アプリケーションに WCF Data Services 5.0 を実装してきましたが、エンティティ オブジェクトを返す読み取り操作に問題はありません。
残念ながら、サービス操作に関しては、プリミティブ型しか返せないという厄介な制限があります ( MSDN を参照)。エンティティ オブジェクトに問題がないことを考えると、非常に面倒です。
WCFDS はそれを認識するため、「ダミー」の複合型を作成することが 1 つの回避策であることはわかっていますが、実際にはデータベースにないデータ モデルにランダムな POCO をスローしたくありません。
そのため、私が思いついた解決策は、サービスによって返される JSON 文字列にシリアル化できるオブジェクトの拡張メソッドを作成することでした。私の質問は; なぜ私がこれをすべきではないか、または誰かがより良い代替案を提案できる理由はありますか?
編集:現在の問題を明確にするための追加情報
私がやっていることの非常に簡単な例を作成しましたが、それはもともとこの質問を提起しました。私のサービスクラスは最初に続きます:
[JsonpSupportBehavior]
public partial class SchedulingService : DataService<ChronosDataContext>, ISchedulingService
{
public static void InitializeService(DataServiceConfiguration config)
{
#if DEBUG
config.UseVerboseErrors = true;
#endif
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
config.SetServiceOperationAccessRule(
"TestService",
ServiceOperationRights.All);
}
[WebGet]
public SchedulingResult TestService(
string testParam1,
string testParam2)
{
// NOTE: I never use the params, they're just there for this example.
SchedulingResult result = SchedulingResult.Empty;
result.Status = OperationStatus.Success;
result.ResponseID = Guid.NewGuid();
result.AffectedIDs = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7 });
result.RecordsAffected = 10;
return result;
}
}
ブラウザを使用してこのサービスにアクセスしようとすると、次のリクエスト エラーが発生します。
The server encountered an error processing the request. The exception message is
'Unable to load metadata for return type
'Chronos.Services.SchedulingResult' of method
'Chronos.Services.SchedulingResult TestService(System.String, System.String)'.'.
See server logs for more details.
The exception stack trace is:
at System.Data.Services.Providers.BaseServiceProvider.AddServiceOperation(MethodInfo method, String protocolMethod)
at System.Data.Services.Providers.BaseServiceProvider.AddOperationsFromType(Type type)
at System.Data.Services.Providers.BaseServiceProvider.LoadMetadata()
at System.Data.Services.DataService`1.CreateMetadataAndQueryProviders(IDataServiceMetadataProvider& metadataProviderInstance, IDataServiceQueryProvider& queryProviderInstance, BaseServiceProvider& builtInProvider, Object& dataSourceInstance)
at System.Data.Services.DataService`1.CreateProvider()
at System.Data.Services.DataService`1.HandleRequest()
at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody)
at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
以下は、返そうとしている SchedulingResult を構成するクラスです。
public class SchedulingResult : ServiceInvocationResponse
{
public SchedulingResult()
: base()
{
this.Payload = new object[]
{
new List<int>(),
new List<int>()
};
}
public List<int> AffectedIDs
{
get { return (List<int>)Payload[0]; }
set { Payload[0] = value; }
}
public List<int> FailedIDs
{
get { return (List<int>)Payload[1]; }
set { Payload[1] = value; }
}
public static SchedulingResult Empty
{
get { return new SchedulingResult(); }
}
}
public class ServiceInvocationResponse : AbstractJsonObject<ServiceInvocationResponse>
{
public ServiceInvocationResponse()
{
this.Status = OperationStatus.Unknown;
this.Severity = ErrorSeverity.None;
}
public virtual int RecordsAffected { get; set; }
public virtual Exception ErrorObject { get; set; }
internal virtual object[] Payload { get; set; }
}
public abstract class AbstractJsonObject<TBaseType>
{
public virtual object Deserialize(string source)
{
return JsonConvert.DeserializeObject(source);
}
public virtual T Deserialize<T>(string source)
{
return JsonConvert.DeserializeObject<T>(source);
}
public string Serialize()
{
return JsonConvert.SerializeObject(
this, Formatting.Indented);
}
public override string ToString()
{
return this.Serialize();
}
public static TBaseType FromString(string json)
{
return JsonConvert.DeserializeObject<TBaseType>(json);
}
}