OData / WCF Service Operation - property access through URI? - wcf

I use a Service Operation in WCF data service to get a object.
[WebGet]
public IQueryable<sample> GetSamples(int Id)
I can retrieve data by
http://localhost:xx/GetSamples?Id=9
Is it possible to get property of the returned object similar to
http://localhost:xx/samples(x)/property
I've tried http://localhost:xx/GetSamples?Id=9/property, and http://localhost:xx/GetSamples/property?Id=9 etc. Nothing works.

If Sample is a complex type then this won't work.
If Sample is an entity type, then it will work with a small modification. Property access is only possible on a singleton result. WCF DS doesn't know that your service operation always returns a single entity, to tell is to, add an attribute SingleResult to your service operation method. Then the first URL should work: service/GetSample/PropertyName?id=2
If the Sample is an entity type and you know the key property value (or values) then service/Samples(keypropertyvalue)/PropertyName should also work.

What about using a select?
http://localhost:xx/GetSamples?Id=9&$select=property

Related

wcf client and sending objects to server

I have a question...
I have a web service where the OperationContract are retrieve and update.
Using a cars example, I have the retrieve providing an object that contains a list of cars and how many cars. I have that configured through a class.
[OperationContract(Name = "**Retrieve**")]
[FaultContract(typeof(FaultInfo))]
[XmlSerializerFormat]
CarInfo Retrieve(CarRequest CarRetrieve);
[OperationContract(Name = "**Update**")]
[FaultContract(typeof(FaultInfo))]
[XmlSerializerFormat]
CarUpdateInfo Update(CarUPDRequest CarUpdate);
Now the retrieve I do not seem to have a problem with at all. It's looking like it's providing the information; the update, however, is not working.
The CarUPDRequest object is defined with different classes and one of those is a list of cars.
The class is constructed much the same as the CarUpdateInfo and that seems to work.
On the client, I know I can would call the update. But I construct the object CarUPDRequest on the client.
I have the service reference namespace like CarService. I can actually type CarService. (and get the list of class methods like the CarInfo and CarUPDRequest.
A couple of things I noticed is like the .Add for a collection defined by a list. On the client app, I DO NOT get the Add. However, if I try the same thing local on the CarService.cs, it will allow me to do the add:
Example:
CarUpd.Cars.car.add doesn't work on the client but does work on the server. Work as in is an option.
When using something like
var CarUpd = new CarUpdRequest();
Is there something I am missing here?
Any assistance on this would be greatly appreciated.
I solved my issue by doing a List CarUpd = new List();

How to pass an entity via a Web Service

Is there a way to pass the data as an entity within another entity? What I'm trying to get to is this: I'm passing customer details to my database, via the webmethod : PostData. What I want is to pass details such as name, surname, etc as string, but I want to group some details, like vehicle details to be passed as : vehicle.Manufacturer vehicle.Model... etc The other data that are not group-able will be passed as an ordinary string. Hope that makes sense. Is there a way to do this?
You can do this either by XML or JSON, so the object that in the part of request will be like in XML :
<VehicleEntity>
<attribute1>value</attribute1>
<attribute2>value</attribute2>
</VehicleEntity>
or Similarly using JSON
VehilceEntity{
attribute1 :value;
attribute2 :value;
}
Basically it is similar to how you are passing parameter, here it is custom parameter VehicleEntity

wcf data services - expose properties of the same type in data model

I'm new to WCF data services. I have a quite simple data model. Some of its properties have the same type, like this:
public IQueryable<IntegerSum> HouseholdGoodsSums
{
get
{
return GetData<IntegerSum>(DefaultProgramID, "rHouseholdGoodsPrice", IntegerSumConverter);
}
}
public IQueryable<IntegerSum> StructureSums
{
get
{
return GetData<IntegerSum>(DefaultProgramID, "rStructurePrice", IntegerSumConverter);
}
}
The IntegerSum is a very very simple class:
[DataServiceKey("Amount")]
public class IntegerSum
{
public int Amount { get; set; }
}
When I navigate to my service in a web browser, I see the following error message:
The server encountered an error processing the request. The exception message is 'Property 'HouseholdGoodsSums' and 'StructureSums' are IQueryable of types 'IntegrationServices.PropertyIntegrationServices.IntegerSum' and 'IntegrationServices.PropertyIntegrationServices.IntegerSum' and type 'IntegrationServices.PropertyIntegrationServices.IntegerSum' is an ancestor for type 'IntegrationServices.PropertyIntegrationServices.IntegerSum'. Please make sure that there is only one IQueryable property for each type hierarchy.'.
When I get rid of one of these two properties, the service starts working.
I searched for this error message in google, but haven't found a solution.
Is it really not allowed to have two properties with the same type in a data model? If so, why?
Comrade,
To address the error first, you're running into a limitation in the Reflection provider. Specifically, the Reflection provider doesn't support MEST.
That said, there are better approaches to achieve what you're trying to achieve. You should probably not make IntegerSum an entity type (an entity type is a uniquely identifiable entity, which doesn't really fit your scenario). While you can't expose that directly, you can expose it as a service operation. That seems much closer to what you're trying to achieve.
A couple of ways to distinguish between whether or not something should be an entity:
If it has a key already, such as a PK in a database, it should probably be an entity type
If you need to create/update/delete the object independently, it must be an entity type
HTH,
Mark

validation based on attributes in metadata class

I am performing validation based on attributes in metadata.cs file. I am using Entity framework 4.0 and using wcf ria services. I want to know what is the equivalent of Page.IsValid in asp.net in silverlight? How do i ensure that the entity is in correct state before saving it? If i do not ensure this an exception fires which looks very ugly. I found a property named entityName.ValidationErrorCount so if my entity is named User i do objUser.ValidationErrorCount is less than equal to 0 i save it. Problem with this approach is if the user doesn't enter value in any of the textbox then subsequently all the values in the entity are null. So ValidationErrorCount property returns 0 because all are null values and thus my program tries to save the entity but naturally the entity is in incorrect state so exception fires. How do i get past this problem?
I hope i am clear. If not, please let me know. Thanks in advance :)
You can validate an entity using the Validator class (from the System.ComponentModel.DataAnnotations
namespace), like so (where entity is a reference to the entity to be validated):
List<ValidationResult> validationResults = new List<ValidationResult>();
ValidationContext validationContext = new ValidationContext(entity, null, null);
bool isValid = Validator.TryValidateObject(entity, validationContext, validationResults, true);
Alternatively, are you using the DataForm control? If so, there's an even easier way to check whether the current item is valid, by calling the ValidateItem() method on the DataForm. This will return a boolean indicating whether the current item is valid (you can also check the IsItemValid property of the DataForm). It will also update the bound controls to show their validation status. If you're not using the DataForm, then it will certainly make it easier if you can. Otherwise, simply add the validation results to the entity's ValidationErrors property:
foreach (ValidationResult result in validationResults)
entity.ValidationErrors.Add(result);
Hope this helps...
Chris

Stored Proc in RIA Services

I want to load some data with a SP.
I've put a SP in a Linq to SQL Class and I don't know how to use it for loading it's data in a datagrid.
In LinqToSqlDomainService I can't figure out how to call a SP.
What steps should I use.
Any samples of this ? All samples use a table.
Thank's
This post should hopefully be of help:
http://blogs.msdn.com/brada/archive/2009/08/24/business-apps-example-for-silverlight-3-rtm-and-net-ria-services-july-update-part-24-stored-procedures.aspx
You can create empty view with the same structure of your sproc and map that stored procedure to your function in your DomainService
See sample on http://cid-289eaf995528b9fd.skydrive.live.com/self.aspx/Public/sproc.zip
I found the following excellent step-by-step guide at this site -
http://betaforums.silverlight.net/forums/p/218383/521023.aspx
1) Add a ADO Entity Data Model to your Web project; Select generate from database option; Select your Database instance to connect to.
2) Choose your DB object to import to the Model. You can expand Table node to select any table you want to import to the Model. Expand Stored Procedure node to select your Stored Precedure as well. Click Finish to finish the import.
3) Right click the DB model designer to select Add/Function Import. Give the function a name (same name as your SP would be fine) and select the Stored Procedure you want to map. If your SP returns only one field, you can map the return result to a collection of scalars. If your SP returns more than one field, you could either map the return result to a collection or Entity (if all the field are from a single table) or a collection of Complex types.
If you want to use Complex type, you can click Get Column button to get all the columns for your SP. Then click Create new Complex type button to create this Complex type.
4) Add a Domain Service class to the Web project. Select the DataModel you just created as the DataContext of this Service. Select all the entitis you want expose to the client. The service functions should be generated for those entities.
5) You may not see the Complex type in the Entity list. You have to manully add a query function for your SP in your Service:
Say your SP is called SP1, the Complex type you generated is called SP1_Result.
Add the following code in your Domain Service class:
public IQueryable<SP1_Result> SP1()
{
return this.ObjectContext.SP1().AsQueryable();
}
Now you can compile your project. You might get an error like this: "SP1_Result does not have a Key" (if you not on RIA service SP1 beta). If you do, you need to do the following in the service metadata file:
Added a SP1_Result metadata class and tagged the Key field:
[MetadataTypeAttribute(typeof(SP1_Result.SP1_ResultMetadata))]
public partial class SP1_Result
{
internal sealed class SP1_ResultMetadata
{
[Key]
public int MyId; // Change MyId to the ID field of your SP_Result
}
}
6) Compile your solution. Now you have SP1_Result exposed to the client. Check the generated file, you should see SP1_Result is generated as an Entity class. Now you can access DomainContext.SP1Query and DomainContext.SP1_Results in your Silverlight code. You can treat it as you do with any other Entity(the entity mapped to a table) class.
Calling a stored procedure is trivial. Import it as a function and then invoke the function as a member of the DDS. The return value is an ObservableCollection<> that you can use to set up the DataContext of the object you want to bind.
...unless you want to use it in a Silverlight RIA app via the magic code generated proxy, in which case your goose is cooked unless your result rows exactly match one of the entities. If you can meet that criterion, edit the DomainService class and surface a method that wraps the ObjectContext method.