After some looking around, I'm getting the feeling that this approach isn't the best one for the issue I'm trying to resolve, but figured I'd have one last attempt at trying to find a resolution here before I move on to a new approach.
I have the current service layout below and I am trying to achieve the following:
Initial request will have a value in the query string and then the rest of the data will be sent up inside a HTML form post application/x-www-form-urlencode
The CsvLookup will extract information from the posted form data, carry out some processing on it and then return a JSON formatted response to the calling client
The goal with using WF is that, once we have written the activities, we can simply swap out the CsvLookup activity for an SQL DB lookup or something else later on down the line without needed to change any code on the server, the data we receive on this service will always be in the same format and will always be expected to be sent back in the same format as well, it is the intermediary stuff we're hoping to address with this approach
As you can see above, at the moment I have all the variables declared individually within this service and inside the activity I have them declared as such.
public InArgument<string> AccessEmail { get; set; }
public InArgument<Guid> PackageId { get; set; }
public InArgument<string> OwnerEmail { get; set; }
public InArgument<string> Ip { get; set; }
public OutArgument<string> Response { get; set; }
My question is hopefully a fairly straight forward on; Is it possible to assign a service variable to accept a form encoded post of data, or do all the variables need to be assigned individually?
Currently when using WcfTestTool, when I connect to the service, I see all the variables listed one after the other for me to declare, really, I want to declare one value for the query string and another for the main form data.
After some digging around, I've discovered that by default, this sort of setup is primarily geared towards SOAP calls, so to get the kind of functionality I'm looking for, it seems like it's a better idea to use a standard WCF service and then control the functionality within a config file.
Related
I'm having a problem to find a standard, how such an update would look like. I have this model (simplified). Bear in mind that Team is allowed without any player and Team can have up to 500 players:
public class Team
{
public int TeamId { get; set; }
public string Name { get; set; }
public string City { get; set; }
public List<Player> Players { get; set; }
}
public class Player
{
public int PlayerId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
and this endpoints:
Partial Team Update (without players): [PATCH] /api/teams/{teamId}. Offers me options to update particular fields of the team, but no players.
Update Team (with players): [PUT] /api/teams/{teamId}. In payload data I pass json with entire Team object, including collection of players.
Update Player alone: [PUT] /api/teams/{teamId}/players/{playerId}
I started wondering if I need endpoint #2 at all. The only advantage of endpoint #2 is that I can update many players in one request. I can delete or add many players at once, as well. So I started looking for any standard, how such a popular scenario is being handled in the real world?
I have two options:
Keep endpoint #2 to be able to update/add/remove many child records at the same time.
Remove endpoint #2. Allow to change Team only via PATCH without ability to manipulate Player collection. Player collection can be changed only by endpoints:
[POST] /api/teams/{teamId}/players
[PUT] /api/teams/{teamId}/players/{playerId}
[DELETE] /api/teams/{teamId}/players/{playerId}
Which option is a better practice? Is there a standard how to handle Entity with Collection situation?
Thanks.
This one here https://softwareengineering.stackexchange.com/questions/232130/what-is-the-best-pattern-for-adding-an-existing-item-to-a-collection-in-rest-api could really help you.
In essence it says that POST is the real append verb. If you are not really updating the player resource as a whole, then you are appending just another player to the list.
The main argument with which I agree, is that the PUT verb requires the entire representation of what you are updating.
The patch on the other hand, I would use to update a bunch of resources at the same time.
There is no really wrong or right way to do it. It depends on how you view the domain at the end of the day.
You can have bulk operations and I would certainly use POST with that. There are some things to consider though.
How to handle partial success. Would one fail the others? If not, what is your response?
How will you send back the new resources url? The new resources should be easily discoverable.
Apart from some design considerations, if you are taking about multiple inserts, you'd better do it in bulk. If it's a couple at a time, save yourself and the people who will consume it some time and go with one by one.
(Edited) -> I have a solution with different projects. It has a strange structure because I'm not an professional software engineer. The solution has three parts: one HMI project (WPF), bussiness project (class library type) and service project (WCF).
In the bussiness project, I do some process that has result which I save in a static class. This results are exposed in the screen by WPF project mentioned previously and now I need to transfer this data by one service placed in the WCF project.
The object is similar to:
[DataContract]
public class ObjectToTransfer
{
[DataMember]
public string ParameterOne = string.Empty;
[DataMember]
public string ParameterTwo = string.Empty;
}
In the other hand, the method that picks up the informtion from static class belonging to bussiness project is like this:
[ServiceBehavior]
public class Service: IService
{
public ObjectToTransfer SendObject()
{
return new ObjectToTransfer{
ParameterOne = BusinessProject.StaticClass.ResultOne,
ParameterTwo = BusinessProject.StaticClass.ResultTwo
};
}
Well, when I consume the service the result is a object with the parameters one and two empty. In additon, when I debug the solution with both projects run, the static class hasn't info in her atributes... It's like whether both projects run independently, in spite of both are under the same solutions..., It's like whether there was no relationship between them. Where is the mistake?
Thank you in advance!
The main thing you will need to do is change the DataContract class to a class with proper getters and setters.
[DataContract]
public class ObjectToTransfer
{
[DataMember]
public string ParameterOne { get; set; }
[DataMember]
public string ParameterTwo { get; set; }
}
The reason this is important is because of the way WCF works when it try to serialize the data from the server to the client. Essentially, the class on the server side schematically matches a generated class on the client. (They share the same class schema.) If there is no proper structure to the class, the data cannot get set. The members are basically read-only.
What you have in your class right now are public member variables, and they are set to always return string.Empty. WCF can't work with that, it is too strict. The server and the client need to be able to read and write to all DataMember properties, so you need the { get; set; }.
Don't forget to refresh your service reference after making this change.
If you need some good resources to learn WCF, check out these videos WCF Tutorial. They are a little dated, but all of the concepts still apply.
This might be late and I am new to WCF service, so I am sharing based on what I have done in my case to share data among different projects.
Background of my project:
I have a WCF service(host), a client and a server project. (A total of 3 different projects.) I will perform the necessary calculation in WCF service. Afterwards, I am suppose to share the result to the client and server. Therefore, there is this variable, variableA, that I have share among the 3 projects.
What I did:
In WCF service, I declare variableA and mark it static:
private **static** string variableA;
Only after I marked variableA as static, then I can see the same variableA across different projects.
I am not sure if this helps but this is what I did in my case.
I'm creating asp.net-mvc application where user is uploading multiple files.
The data will be compared with db data, processed and exported later. Also paging.
When displaying these data, sorting and filtering is importing.
When data is uploaded, some of them will be stored in db, some will be displayed as not found in db, some will be modified and stored ... etc
My question is, what is the best way to store the uploaded data in order to be available to be process or viewed?
Load in memory
Create temp tables for every session? (even don't know if possible)
Different storage which can be queryable (access data using linq) (JSON??)
Another option.
The source files are (csv or excel)
One of the files example
Name Age Street City Country Code VIP
---------------------------------------------------------
Mike 42 AntwSt Leuven Belgium T5Df No
Peter 32 Ut123 Utricht Netherland T666 Yes
Example of class
public class User
{
public string Name { get; set; }
public Address Address { get; set; } // street, city,country
public Info Info { get; set; } // Age, and Cres
}
public class Info
{
public int Age { get; set; }
public Cres Cres { get; set; }
}
public class Cres
{
public string Code { get; set; }
public bool VIP { get; set; }
}
There are a variety of strategies for handling this (I actually just wrote an entire dissertation over the subject), and there are many different considerations you'll need to take under consideration to achieve this.
Depending on the amount of data present, and what you're doing with it, it may be simple enough to simply store information in Session Storage. Now how you actually implement the session store is up to you, and there are pros and cons to how you decide to do that.
I would personally recommend a server side session store to handle everything and there are a variety of different options for how to do that. For example: SSDB and Redis.
Then from there, you'll need a way of communicating to clients what has actually happened with their data. If multiple clients need to access the same data set and a single user uploads a change, how will you alert every user of this change? Again, there are a lot of options, you can use a Pub/Sub Framework to alert all listening clients. You could also tap into Microsoft's SignalR framework to attempt to handle this.
There's a lot of different If's, But's, Maybe's, etc to the question, and unfortunately I don't believe there is any one perfect solution to you problem without knowing exactly what you're trying to achieve.
If the data size is small and you just need them to exist temporarily, feel free to go with storing them in memory and thus cut all the overhead your would have with other solutions.
You just need to be sure to consider that the data in memory will be gone if the server or the app is switched off for whatever reason.
It might also be a good idea to consider, what happens if the same user performs the operation for the second time, while the operation on the first data is not completed yet. If this can happen to you (it usually does), make sure to use good synchronization mechanisms to prevent race conditions.
I am creating a WPF Smart Client app which uses WCF and NHibernate on the back end. I am making good progress but have a question with regards how to get databack from the WCF Service to enable buttons / functionality in the WPF smart client.
At the moment I have a CreateProduct screen which ultimately calls WCFProductService.CreateProduct(ProductDTO productDetails) to the WCF service. This works fine and creates a product record in the database. The CreateProduct method does not currently return anything.
I do not want to create a massive DTO in memory then send that across the wire. I am aiming to do something more along the lines of Create The Product then AddSomething, AddSomething else as seperate tasks.
To this end I have a button AddAttribute. Add Attribute has to work in the context of a product at the WCF service level so I need to send a ProductId in the AddAttributeDTO. Of course at this stage the ProductDTO does not have an Id in it as it has been created entirely in memory before being sent off to the WCF Service.
I assume that the WCF service call CreateProduct will need to return some sort of object that contains the Id and other data
What form should this take?
Are there any documents on guidance / best practice for this?
How can then I use this to enable the relevant buttons?
Thanks in advance for any assistance
Alex
You can simple return a DTO back to the consumer, adding whatever information you need to.
public class AddProductResponse
{
public string ProductId { get; set; }
}
Your OperationContract would then look like
public AddProductResponse AddProduct(YourProductDto dto)
{
}
I would also add the your idea about adding 'parts' to an already existing product is probably overkill. Unless you product contains literally 100000's of attributes, it will not consume anywhere near the sort of memory you should worry about. It will be a lot cleaner and simpler to maintain having a single DTO with corresponding methods for adding, updating, etc.
I want to have an class like this,
public class Apple
{
public string Size { get; set;}
public string Colour { get; set;}
public string Shape { get; set;}
public int appleId { get; set;}
}
I want to expose that over web services using some web methods like this,
public void AddApple(Apple apple)
{
}
public Apple GetApple(int appleId)
{
}
So when I add a service reference in visual studio to that webservice I get client proxy objects generated for me allowing me to create an Apple on the client side and send that through to the webservice.
Is there a way for me to make one of those properties read only on the client side? I need the setters there so that I can set the values on the server side, but I want to control which data they can update on the client side.
Any ideas?
What I could do is pass in some of the data in the constructor, and only expose getters on the ones I want to be read only, but I want to use an object mapper on the server side. That means ideally I would want to leave the setters there.
In general, you cannot assume control over proxies generated at client side. So correct way would be to ignore values sent by client (or raise exception if he changes those values). The service documentation has to be explicitly mention such things.
Edit:
Yet another work-around would be to divide your data class into two classes - one non-editable by client (say Apple1) and another editable - say Apple2. So now service update method can only accept Apple2 so that client can know looking at generated proxy code what he can change. On server side, you can have Apple1 inherited from Apple2 to have complete data but I believe that proxy generated at client will/can anyway have two different unrelated classes. Perhaps better way in such case would be to have composite full AppleFull containing Apple1 and Apple2.
Please refer to the following question and its answers, I just skimmed through your question but I believe that it is a simillar problem as I faced -
WCF serialization and Value object pattern in Domain Driven Design
Another way to achieve that would be to share the assembly containing the Apple class (but no server side component) between server and client. Make the setters internal and mark the server side assemblies as friends using the InternalsVisibleTo attribute.
This will allow the server to use the setters but not the client.