WCF DataContract mismatch - c#

We have this middle tier (WCF) deployed in a IIS. Sometime, DataContact changes property data type. i.e (StudentID)
From:
[DataContact]
public class Student
{
public int StudentID { get; set; }
public string Name { get; set; }
}
To:
[DataContact]
public class Student
{
public string StudentID { get; set; }
public string Name { get; set; }
}
Question: Is there a way to tell the client or send a message (error) to client that the DataContract changed?

WCF support versioning capabilities.
However, when you Modify return value types then An exception will occur if the return value from the service cannot be converted to the expected data type in the client version of the operation signature.
The important distinction to understand is that there are certain changes which are breaking and other non-breaking changes. For e.g. If you add a new method to the WCF Service, then it's a Non-Breaking change, but if you remove the method it's a breaking change for the clients.
For Additional reading, read here at msdn
During the design for WCF Services, it is recommended to Services version tolerant, so that client on different version can work with the Service. Also, you would need to communicate the changes using email/document etc. I do not believe there is out of box support for Managing notifications. It appears to be an administrative work for which you can otherwise do using other communication medium like emails etc.

Related

Add constructors to auto-generated OpenAPI service client

I've got a Blazor WebAssembly project with an ASP.NET WebAPI hosted service. If I use the auto-generated code in the "Connected Services" in Visual Studio to retrieve the OpenAPI definition, I get a nice proxy representing all of the HTTP endpoints, complete with request and reply objects.
But the generated request/reply classes have only a default constructor and properties, like:
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.0.22.0 (Newtonsoft.Json v11.0.0.0)")]
public partial class GetDetailedMessageRequest
{
[Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public long Id { get; set; }
}
I prefer to have at least the option of a constructor with each of the properties - this is actually the way the classes are in the service side:
public class GetDetailedMessageRequest
{
public GetDetailedMessageRequest() { }
public GetDetailedMessageRequest(long id)
{
ID = id;
}
public long ID { get; set; }
}
Is there any way to either have the code generator build these constructors, or tell it not to create the model classes at all, and instead let both the client reference the shared models project?
Neither of these seems likely - I can think of a couple workarounds, like manually editing the generated code, or creating the request on the client using the class from my shared project, serializing it, deserializing it into the generated class type, or possibly just building the constructors again in new partial classes for all of these...But obviously those are not ideal.
I could always build my own code generator, or skip the generated stuff altogether and just use HttpClient normally - but I like the idea of an auto-generated proxy class.

Does UTF-8 encoding have to be explicitly defined in a web service response?

I am supporting a C# (.asmx) web service built on .NET 3.5. It is a very, very simple service that returns, among a few other things, a street address. The scope of the application that provides the service was recently widened and now the DB behind it houses international addresses as well. This means Latin foreign language characters can be stored (accent marks, umlauts, etc) and consequently returned in a web service response.
When I test the service locally using soapUI's automatically generated requests and without adding any special headers or any other intstructive information, I see this element exactly as it's stored in the database - with its accent mark:
<CompositeStreet>140-146 RUE EUGÈNE DELACROIX</CompositeStreet>
However, when a connecting system calls the service the IT staff report that the response contains the question mark typically used as the replacement for a non-supported character:
<compositeStreet>140-146 RUE EUG?NE DELACROIX</compositeStreet>
I'm unsure whose issue this is and I'm concerned that the simplistic design of the service may mean that it falls on my shoulders to recode to somehow ensure any consumer is guaranteed to see the data in UTF-8 encoding. I've been under the impression that UTF-8 was the default encoding and nothing explicit was required. (Please save the discussion about upgrading to WCF for another thread - it's not in scope for this right now.)
Can you have a look at the structure of the service and tell me if there is actually something that needs to be done on my side? (Code drastically slimmed down for the sake of this discussion)
The ASMX page - basically the WebMethod accepts a request and returns the response:
namespace Company.IT.Network.LocationStore.LS_Services
{
using . . .;
[WebService(Namespace = "Company.IT.Network.LocationStore.LS_Services.ClliRecordService")]
public class ClliRecordService : System.Web.Services.WebService
{
public ClliRecordService() { }
[WebMethod(Description = "Lengthy description")]
public VZBServiceResponse ClliLookup_VzbSite(VZBServiceRequest sRequest)
{
VZBServiceResponse sResponse = new VZBServiceResponse(sRequest);
return sResponse;
}
}
And the serializable class that is a property of the VZBServiceResponse type which ends up in the XML response. You'll see all there is is the [Serializable] attribute and the setting of the order of the elements returned.
namespace Company.IT.Network.LocationStore.LS_Lib.BO
{
using ...;
[Serializable]
public class Address
{
private string _compositeStreet;
private string _buildingName;
[XmlElement(Order = 0)]
public string BuildingName
{
get { return _buildingName; }
set { _buildingName = value; }
}
[XmlElement(Order = 1)]
public string CompositeStreet
{
get { return _compositeStreet; }
set { _compositeStreet = value; }
}
}
}
There is really not much more to it than that. No formatting of the XML response through a memory stream (which I've seen in some posts) or specific handling through Serialize or Deserialize methods.
Are there recommendations to improve on this so that service consumers are guaranteed to be presented foreign language characters or is that really up to the calling system? Thank you for any guidance!

WCF Property wont set in response

i have a problem with WCF service.. i am using service reference in windows app project. In Reply to one of my wcf methods there is a class which has a propety ID int (datacontract) it always comes 0. When i try from code it works. but when i actually installl the wcf service and try it comes 0. any idea guys ? some settings with proxy? anything at all?
[DataMember(Order = 1)]
public int ID { get; set; }
[DataMember(Order = 2)]
public int Quantity { get; set; }
now quantiy is populated, but ID is always 0. I chekcd the database calls, ID and quantiyt is returned. also mapping are all correct. From code i get both values but when i install setup this ID field never retuned
This problem was related to multilingual application. This code worked fine for English, but in other language login it failed.
Reason being, In request parameter dates were passed, and for login other than english, date comparison used to fail.

Save socket as type object and cast when used

I am creating a crossplatform application using Mono that can use different kinds of connection types (Bluetooth, WiFi etc.) but at any given time it will always only have one socket connection.
What connection type is used is decided at compile time
I want this socket connection to be accessible to all my different pages of my application that needs it, then below an interface they will have their specific implementation (For example a Android Bluetooth implementation) that always needs android.bluetooth.BluetoothSocket so I cast it to that.
So my Views and ViewModels dont know what kind of socket it is
My reason for this would be to able to hide it all behind one interface and just have a property
Public Interface MyContainer
{
Bool Connected { get; set; }
Object Socket { get; set; }
}
Would this be very very bad code? I can't find any other reasonable way to hide the Socket behind an Interface when it changes depending on platform and connectiontype
You can make your class generic to avoid using object.
So, for example you would use:
public class MyContainer<T>{
...
T Socket { get; set; }
...
}
and then use it like:
MyContainer<BlueToothSocket> container = new MyContainer<BlueToothSocket>();
BlueToothSocket socket = container.Socket;

Will the static public variables in my app get shared with other users in the same app?

For reasons I would rather not discuss, I need to create a custom authentication system for my app. I was just reviewing the system and am having some doubts if my solution is thread safe. My goal was to create a solution that would allow my app to authenticate a user one time and that users authentication info would be shared by all master pages, pages, classes, user controls, etc that are used. (But not share the same info between users)
Here is my setup:
PageHttpModule.cs - this is added to the web.config as a httpModule.
public class PageHttpModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.AuthenticateRequest += new EventHandler(OnAuthenticateRequest);
}
public void OnAuthenticateRequest(Object s, EventArgs e)
{
CurrentUser.Initialize();
}
public void Dispose() { }
}
CurrentUser.cs
public static class CurrentUser
{
public static bool IsAuthenticated { get; private set; }
public static string Email {get; set;}
public static string RealName {get; set;
public static string UserId {get; set;}
public static void Initialize()
{
CurrentUser.AuthenticateUser();
}
Note: this is a scaled down version of my authentication code.
public static void AuthenticateUser()
{
UserAuthentication user = new UserAuthentication();
user.AuthenticateUser();
if (user.IsAuthenticated)
{
CurrentUser.IsAuthenticated = true;
CurrentUser.UserId = user.UserId;
CurrentUser.Email = user.Email;
CurrentUser.RealName = user.RealName;
}
}
}
UserAuthentication.cs
public class UserAuthentication
{
public string Email { get; set; }
public string RealName { get; set; }
public string UserId { get; set; }
public bool IsAuthenticated { get; private set; }
public UserAuthentication()
{
IsAuthenticated = false;
Email = String.Empty;
RealName = String.Empty;
UserId = String.Empty;
}
public void AuthenticateUser()
{
//do some logic here.. if the user is ok then
IsAuthenticated = true
Email = address from db
UserId = userid from db;
Realname = name from db;
}
}
I have tested between 3 different browsers and it seems to work fine, but I am still learning and don't want to make a huge mistake.
If my logic is totally wrong, then how should I do it so I dont have to put user lookups on every page directly?
No, this is not thread-safe. For instances of the application living in separate processes or AppDomains, this will be just fine. But if your ASP.NET server is going to serve multiple requests at once using threading, you are going to have some very bad side effects if two people try to use the application at the same time.
In the Init method, the HttpApplication parameter is described as:
An HttpApplication that provides access to the methods, properties, and events common to all application objects within an ASP.NET application
The key here is that there is one PageHttpModule for the lifetime of the app, and all static objects that exist in the lifetime of the app will share those variables.
BUT... the lifetime of CurrentUser is only within the scope of the OnAuthenticateRequest event, unless some other reference keeps the object alive. If it were a PageHttpModule member-level variable, you'd have issues that you would have noticed immediately. In your situation, however, you'll work fine so long as you don't get more than one simultaneously-processed OnAuthenticateRequest call.
The answer to your question is no, you're not guaranteed to be thread-safe. If two authentication requests come in simultaneously, you're not guaranteed to have one event complete before the other begins, in which case the second user can appear authenticated, when it's really the first user that was logged on.
Update
I think part of the problem is coming from a misunderstanding of AuthenticateRequest... By the time this event is called, the user has already been authenticated by either Windows or Forms authentication... you're just getting notified that it's happened. In fact, the property User.Identity.IsAuthenticated has already been set (I believe this event fires even if the user fails authentication, but I won't swear to that without double-checking).
If I understand what you are after, you're really trying to write your own custom membership provider. If you take this approach, you will have all the benefits of the built-in authentication... all of the standard properties related to authentication will be set and accessible, and will be isolated to a user's session in the manner you want.
Writing a custom provider is not a small feat, but it is doable, and you should be able to reuse a lot of the logic and code you're currently using for your classes.
Trying to completely re-write the authentication mechanism would be jumping through painful, complicated hoops.
Some links:
http://www.devx.com/asp/Article/29256/0/page/3
http://www.codeproject.com/KB/aspnet/WSSecurityProvider.aspx
http://msdn.microsoft.com/en-us/library/f1kyba5e%28v=VS.90%29.aspx
The properties you must implement may look daunting, but unless you need a specific functionality (such as ResetPassword), you can simply throw a NotImplementedException. Code only what you'll use.
Why not just do it the way microsoft recommends?
http://msdn.microsoft.com/en-us/library/9wff0kyh.aspx
I've done custom authentication this way and it works fine.
Here is another link which should prove useful:
Link
What you have done with IHttpModule seems like a good path to tackle this kind of issue. One of the purposes of the http module as stated by microsoft is to enable for any kind of special authentication. When http module intializes it uses the same instance for new requests. Since you dont have any global variables I am not so sure how to address your thread safe question. It seems like you are onlu reading some data out, so please elaborate!

Categories