I have a DataService class on top of a Entity Framework 5 DbContext:
public class MyDataService : DataService<MyDbContext>, IServiceProvider
{
[WebGet]
public IQueryable<Product> GetProducts1(int category)
{
return from p in this.CurrentDataSource.Products
where p.Category == category
select p;
}
}
Now I want to expose methods from my DbContext to the DataService and used this sample code: http://efactionprovider.codeplex.com/
public class MyDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
[NonBindableAction]
public IQueryable<Product> GetProducts2(int category)
{
return from p in this.CurrentDataSource.Products
where p.Category == category
select p;
}
}
Accessing http://localhost:12345/MyDataService.svc/$metadata show that both methods are known, but the first one hat a
m:HttpMethod="GET"` attribut
<EntityContainer Name="MyDbContext" m:IsDefaultEntityContainer="true">
...
<FunctionImport Name="GetProducts1" ReturnType="Collection(MyNameSpace.Product)" EntitySet="Products" m:HttpMethod="GET">
<Parameter Name="category" Type="Edm.Int32" Nullable="false"/>
</FunctionImport>
<FunctionImport Name="GetProducts1" ReturnType="Collection(MyNameSpace.Product)" EntitySet="Products">
<Parameter Name="category" Type="Edm.Int32" Nullable="false"/>
</FunctionImport>
...
I can execute GetProducts1 by accessing the url
http://localhost:12345/MyDataService.svc/GetProducts1?category=1
That doesn't work for GetProducts2 (propably because of GET not allowed) But I managed to execute GetProducts2 by using fiddler:
POST: http://localhost:12345/MyDataService.svc/GetProducts1
Request Headers:
User-Agent: Fiddler
Host: localhost:12345
Content-Length: 12
Content-Type: application/json
Request Body:
{category:1}
Ok, now here is my problem: I consume this service with a Windows application using a Service Reference. Since the code generation in the DataServiceContext
derived class does not cover the actions I need to call them by myself.
For the first one (GetProducts1
) I can do:
public IEnumerable<Product> GetProducts1(int category)
{
var proxy = new MyDataServiceContext(
"http://localhost:12345/MyDataService.svc");
var queryString = String.Format("{0}/GetProducts1?category={1}",
proxy.BaseUri, category);
var uri = new Uri(queryString, UriKind.RelativeOrAbsolute);
return proxy.Execute<Product>(uri);
}
But I am struggling with the second one. I tried:
public IEnumerable<Product> GetProducts2(int category)
{
var proxy = new MyDataServiceContext(
"http://localhost:12345/MyDataService.svc");
var queryString = String.Format("{0}/GetProducts2",
proxy.BaseUri);
var uri = new Uri(queryString, UriKind.RelativeOrAbsolute);
return proxy.Execute<Product>(uri, "POST", false,
new UriOperationParameter("category", category));
}
but I get a DataServiceClientException: Content-Type-Header value missing.
(Status-Code 400)
Is there any way to call this method my using the Execute method? I would prefer to continue using the DataServiceContext
and not make any raw Requests myself.
Thanks in advance
btw.
I am using visual studion 2010 and the Microsoft.Data.Services
and Microsoft.Data.Services.Client
packages from nuget rather than the default System.Data.Services
dlls, because I believe I need to set config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
for executing actions in the first place.
Try using BodyOperationParameter instead of UriOperationParameter. Action parameters are included in request body instead of Uri.