I've encountered two oddities concerning a Web API stateless service in my service fabric cluster. The first regarding missing properties on the response to a call to a stateful service. The second being a critical error when a response to GET was changed from a class to a struct. Details below.
Issue #1 - Missing Properties
I have a three projects:
A class library with a class called Person. The two projects below utilize this library view a private nuget package.
A Stateless Web API, which has a GET to retrieve all Persons.
A Stateful Service, implementing a ReliableDictionary which holds all persons. The Stateless Web API calls a method which returns all person from this dictionary.
The issue is that I've recently updated my class library to give Person some new properties (say, CreatedOn). Both the Stateless Web API and Stateful Service have the latest version of this package and were deployed (overridding, not upgrading). The Stateful Service correctly recognizes and stores these new properties. However, the Web API is somehow not creating an object without those new properties. It's not like they are null, they just simply do not exist!
I've tried uninstalling/reinstalling nuget package, as well as, clearing out bin/obj folders. Neither works. However, creating a new Web API Service fabric project, does work.
Any ideas, or has my project somehow been corrupted?
Pictures of properties:
Issue #2 - Struct Crashing Web API
This may be related to the first issue, and uses the same libraries and services. I tried changing the Person object to a struct, but any call to the api then throws the following error:
{
"Message": "An error has occurred.",
"ExceptionMessage": "The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " at System.Web.Http.Routing.RouteCollectionRoute.get_SubRoutes()\r\n at System.Web.Http.Routing.RouteCollectionRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request)\r\n at System.Web.Http.HttpRouteCollection.GetRouteData(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpRoutingDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Net.Http.DelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Web.Http.HttpServer.d__0.MoveNext()"
}
Again, trying this in another, identical Web API project works just fine.
Thoughts?
I got same when I used badly formatted route
example
[Route("/api/info")]
correct is
[Route("api/info")]
Related
I'm trying to figure out if it is possible to handle all exceptions that had been thrown by the bunch of microservices in certain one.
For example, i have microservice called ui. It handles all ui related stuff and serves as a Zuul gateway. It contains custom error page. Also i have microservice called foo. When foo throws exception i want ui to handle it i.e show ui's custom error page. I dont want foo or any other service to contain any error pages.
Is there a way to achieve such behavior?
I would suggest using an error controller and then having all your micro services redirect to that uri when experiencing an error.
Check out this tutorial he explains setting up a custom error page pretty well.
http://www.baeldung.com/custom-error-page-spring-mvc
I have made a REST web api and I thought the application_start() event of a web api should triggered once you start the web service from IIS manager, however, what I have observed to my web api is it only triggered by the first web request which reached to the web service. I was wondering if this is supposed to be or I did it incorrectly? Thanks.
That's how it is. From the docs:
Called when the first resource (such as a page) in an ASP.NET
application is requested. TheĀ Application_Startmethod is called only
one time during the life cycle of an application. You can use this
method to perform startup tasks such as loading data into the cache
and initializing static values.
https://msdn.microsoft.com/en-us/library/ms178473.aspx
We are working on an internal MVC3 app that purely uses Windows Authentication. There's a view that does an AJAX call to a controller action that does some processing before calling a web service. The problem we are running into is that if Anonymous access is turned off (as in Windows Authentication is on), calling the service from the controller actions results in a 401: Unauthorized error.
We have run into a problem of the double hop issue where credentials aren't passed correctly from server to server when calling a service within a service. I'm wondering if the AJAX call is somewhat mimicing the same behavior and not transmitting the correct Windows credentials to the controller which then doesn't pass the correct credentials to the web service.
I've seen some posts that shows how to pass a username and password along with the jQuery call but nothing mentions, an effective way, to bring along Windows Authentication with it.
Has anyone run into a similar issue? We would rather not leave Anonymous access on the web service as it is somewhat sensitive data that we would like to control access to.
Do you have identity impersonation turned on as described in this question:
How to get Windows user name when identity impersonate="true" in asp.net?
A colleague did some research over the weekend and determined it may have something to do with Kerberos authentication setup on the server as well as the jQuery call. In order to get around it, we just refactored the web service into a library that the application just references. We made it a web service initially as we thought in the future this data would need to be accessed from other applications. Running into this issue, we will most likely make it into a NuGet package.
Thanks for the comments.
I'm using a Web Service that has a endpoint of http://api.domain_a.com/ and using Visual Studio I can easily generate a proxy class to work with the service easy and simple.
But I want to create a way that users can use their own service (and access their own data, instead my own) and I wanted to know if there is a way that I can change the base URL of the Service on-the-fly.
As an example
I generate the proxy classes by adding the Web References to my project, but now, per each request I have a User Name that I will get the User Settings (witch contains their URL), how can I (if it's a possibility) tell the generated proxy that I'm using domain http://domain_b.com/api instead of the original that I used when adding the Web References?
Do I need to call the service manually? Sending and Receiving XML data? or there is a "switch" that I can use to point to the new URL?
If you're using .NET 2.0, each of those proxy classes should have a URL property. Simply update the URL property and the proxy will point to the new service.
If you're using WCF then things get a little more complicated, but not by much. You just have to change the Endpoint Address:
var service = new ServiceClient();
string url = "http://domain_b.com/api";
EndpointAddress newAddress = new EndpointAddress(url);
service.Endpoint.Address = newAddress;
Haven't seen many Geneva related questions yet, I have posted this question in the Geneva Forum as well...
I'm working on a scenario where we have a win forms app with a wide installbase, which will be issuing frequent calls to various services hosted by us centrally throughout it's operation.
The services are all using the Geneva Framework and all clients are expected to call our STS first to be issued with a token to allow access to the services.
Out of the box, using the ws2007FederationHttpBinding, the app can be configured to retrieve a token from the STS before each service call, but obviously this is not the most efficient way as we're almost duplicating the effort of calling the services.
Alternatively, I have implemented the code required to retrieve the token "manually" from the app, and then pass the same pre-retrieved token when calling operations on the services (based on the WSTrustClient sample and helpon the forum); that works well and so we do have a solution,but I believeit's not very elegant as it requires building the WCF channel in code, moving away from the wonderful WCF configuration.
I much prefer the ws2007FederationHttpBinding approach where by the client simply calls the service like any other WCF service, without knowing anything about Geneva, and the bindings takes care of the token exchange.
Then someone (Jon Simpson) gave me [what I think is] a great idea - add a service, hosted in the app itself to cache locally retrieved tokens.
The local cache service would implement the same contract as the STS; when receiveing a request it would check to see if a cahced token exists, and if so would return it, otherwise it would call the 'real' STS, retrive a new token, cache it and return it.
The client app could then still use ws2007FederationHttpBinding, but instead of having the STS as the issuer it would have the local cache;
This way I think we can achieve the best of both worlds - caching of tokens without the service-sepcific custom code; our cache should be able to handle tokens for all RPs.
I have created a very simple prototype to see if it works, and - somewhat not surprising unfortunately - I am slightly stuck -
My local service (currently a console app) gets the request, and - first time around - calls the STS to retrieve the token, caches it and succesfully returns it to the client which, subsequently, uses it to call the RP. all works well.
Second time around, however, my local cahce service tries to use the same token again, but the client side fails with a MessageSecurityException -
"Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security."
Is there something preventing the same token to be used more than once? I doubt it because when I reused the token as per the WSTrustClient sample it worked well; what am I missing? is my idea possible? a good one?
Here's the (very basic, at this stage) main code bits of the local cache -
static LocalTokenCache.STS.Trust13IssueResponse cachedResponse = null;
public LocalTokenCache.STS.Trust13IssueResponse Trust13Issue(LocalTokenCache.STS.Trust13IssueRequest request)
{
if (TokenCache.cachedResponse == null)
{
Console.WriteLine("cached token not found, calling STS");
//create proxy for real STS
STS.WSTrust13SyncClient sts = new LocalTokenCache.STS.WSTrust13SyncClient();
//set credentials for sts
sts.ClientCredentials.UserName.UserName = "Yossi";
sts.ClientCredentials.UserName.Password = "p#ssw0rd";
//call issue on real sts
STS.RequestSecurityTokenResponseCollectionType stsResponse = sts.Trust13Issue(request.RequestSecurityToken);
//create result object - this is a container type for the response returned and is what we need to return;
TokenCache.cachedResponse = new LocalTokenCache.STS.Trust13IssueResponse();
//assign sts response to return value...
TokenCache.cachedResponse.RequestSecurityTokenResponseCollection = stsResponse;
}
else
{
}
//...and reutn
return TokenCache.cachedResponse;
This is almost embarrassing, but thanks to Dominick Baier on the forum I no now realise I've missed a huge point (I knew it didn't make sense! honestly! :-) ) -
A token gets retrieved once per service proxy, assuming it hadn't expired, and so all I needed to do is to reuse the same proxy, which I planned to do anyway, but, rather stupidly, didn't on my prototype.
In addition - I found a very interesting sample on the MSDN WCF samples - Durable Issued Token Provider, which, if I understand it correctly, uses a custom endpoint behaviour on the client side to implement token caching, which is very elegant.
I will still look at this approach as we have several services and so we could achieve even more efficiency by re-using the same token between their proxies.
So - two solutions, pretty much infornt of my eyes; hope my stupidity helps someone at some point!
I've provided a complete sample for caching the token here: http://blogs.technet.com/b/meamcs/archive/2011/11/20/caching-sts-security-token-with-an-active-web-client.aspx