How to talk to TFSOData service from Silverlight 5 application - c#

I'm trying to obtain information from an online TFS server. The endpoint address for the OData service is: https://tfsodata.visualstudio.com/DefaultCollection.
I try and authenticate with this service using basic authentication as per:
_context = new TFSOData.TFSData(new Uri("https://tfsodata.visualstudio.com/DefaultCollection", UriKind.Absolute));
_context.SendingRequest2 += (object sender, SendingRequest2EventArgs e) =>
{
String creds = String.Format(CultureInfo.InvariantCulture, #"{0}\{1}:{2}", "mydomain", "myusername", "mypassword");
var bytes = Encoding.UTF8.GetBytes(creds);
var credstring = Convert.ToBase64String(bytes);
e.RequestMessage.SetHeader("Authorization", "Basic " + credstring);
};
Unfortunately I always get an exception returned from the eventArgs of my LoadCompleted Callback when I try and run a query on the Odata service and the query I'm running comes back empty when I know it shouldn't be.
{System.Security.SecurityException: Security error.}
Am I doing anything wrong security wise? I've tested my alternate credentials for this odata service in the browser and they work fine.
Just to reiterate, I'm doing this in a silverlight 5 project. I've had a similar method working in WPF before using e.requestheaders.add etc., but that's not available to me in Silverlight.
EDIT:
I've also noticed from using Fiddler that it's going to the clientaccesspolicy.xml file and then not continuing on to actually get the data I wanted from the service. Obviously this is the difference between the WPF app and the Silverlight app, however looking at the clientaccesspolicy.xml and crossdomain.xml files I can see that they are both allowing * and so I should be able to access what I want.

This was because the server was not setup to allow Cross Origin Resource Sharing.

Related

Blazor Server App on Azure: AuthenticationException: The remote certificate is invalid according to the validation procedure

I'm developing a Blazor Server App with VS2019. When running locally (debug or release) it is running and working fine. After publishing it to Azure App Services I get the remote certificate invalid message. At the moment I call a controller method.
Part if the razor page code is:
protected override async Task OnParametersSetAsync()
{
await Task.Run(async () => await GetExperimentInfo());
}
protected async Task GetExperimentInfo()
{
if (string.IsNullOrEmpty(eid))
{
ExperimentName = "Experiment entity not provided";
return;
}
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(NavigationManager.BaseUri);
ExpInfo = await client.GetFromJsonAsync<ExperimentInfo>("api/experiment/" + eid);
if (ExpInfo == null)
{
ExperimentName = "Error: Experiment not found";
return;
}
ExperimentName = ExpInfo.Name;
}
The 'eid' is specified as an argument calling the razor page.
When calling the controller GET method in the server app on Azure App Service directly returns the correct information.
Calling the same controller GET method from within the razor page returns the AuthenticationException of invalid remote certificate!
The method called in the controller is:
[Route("api/experiment/{eid}")]
[HttpGet]
public ExperimentInfo GetExperimentInfo(string eid)
{
var ExpInfo = GetSNExperimentData(eid);
return ExpInfo;
}
I've browsed a lot of articles on the web, but so far did not find a correct answer why and how to resolve this.
Anyone any idea or experience? Thx
The problem was solved by Microsoft Azure Support (by Kevin Kessler) with the following explanation:
This indicates that whichever Root CA is within the remote web service's certificate chain, is not trusted. This is due to the Root CA not being contained within the app service's Trusted Root store.
The Azure web app resides on an App Service Environment (ASE). In this case you may be able to resolve the issue by uploading the needed certificates and assigning their thumbprint values to the app service settings.
Please see this document, which covers the use of certificates on an ASE and how to configure on an app service:
https://learn.microsoft.com/en-us/azure/app-service/environment/certificates#private-client-certificate
Additionally, this StackOverflow article may provide further guidance:
How to make the azure app service trust the certificates issued by the OnPrem CA?
Resolution: Uploaded Root and intermediate certificates to ASE

C# Web Service (404) Not Found.

This code used to work and now it stopped working :/
I'm using the same code in other areas of my application and can call the link which works fine. But in this specific section of my application, it stopped working.
This link is valid and as stated above, it used to work.
Here is the code.
WebClient client = new WebClient();
string xmlResult = client.DownloadString(_workContext.AccountingWebServiceLink + "?action=updateprimary&xml=" + strXML);
I'm not sure if I need to increase the size of bytes in IIS? I suspect it might have something to do with the amount of data being sent.

Unable to access host created by Nancy using external IP

I am creating a Nancy Module that will eventually be hosted inside of a Windows Service. To start the Nancy hosting, I am using Nancy.Hosting.Self. Below is the code to start Nancy host.
string strHostProtocol = Convert.ToString(ConfigurationManager.AppSettings["HostProtocol"]);
string strHostIP = Convert.ToString(ConfigurationManager.AppSettings["HostIP"]);
string strHostPort = Convert.ToString(ConfigurationManager.AppSettings["HostPort"]);
//Here strHostProtocol="https", strHostIP = "192.168.100.88" i.e. System IPv4, strHostPort = "9003"
var url = strHostProtocol + "://" + strHostIP + ":" + strHostPort;
//url ="https://192.168.100.88:9003"
this.host = new NancyHost(new Uri(url));
this.host.Start();
Now once the windows service starts, it will start the above host and I could see this in netstat -a command. When I browse this in browser using https://192.168.100.88:9003 I will get proper response.
The problem arises when the same is browsed using its external IP. Say this system has been assigned with external IP of 208.91.158.66 and when I try browsing this as https://208.91.158.66:9003 I will just get a browser default loading progress continuosly which does not stop and without any error thrown. I have also added the below command and reserved URL successfully.
netsh http add urlacl url=https://192.168.100.88:9003/ user=everyone
But even after this the host cannot be browsed using external IP assigned to that system. Is there any restricting Nancy is putting up? Firewalls are turned off, defenders are turned off. Anyone has any idea on this?
UPDATE
The duplicate linked question talks about LAN but here I am trying through external IP and I've tried answer mentioned over there and also specified the same in question
Alright. This issue was also posted to GitHub Nancy Repo and below is what #Khellang had to say.
When you bind to https://192.168.100.88:9003, the
TcpListener/HttpListener won't listen on other interfaces. You either
have to bind to https://208.91.158.66:9003 or https://localhost:9003
and set RewriteLocalhost = true (default).
Further he also said that
If you also want to listen to requests coming to the external IP, yes.
Or you could use a wildcard, like https://+:9003/, https://*:9003/ or
https://localhost:9003/ (with RewriteLocalhost = true, this will
result in https://+:9003/). You can read more about them in the link I
posted.
and thanks to #TimBourguignon as he suggested the same in his comments. Hope this helps someone in future.
He has also suggested to read this link to know more about the Strong Wildcard and Weak Wildcard

How to host a simple ASP.NET web interface in a Windows Services

For a simple appliance that runs on a Windows & .NET operating system, we need to create a simple configuration web interface to control it. Just like your router's configuration page, nothing more complicated than that.
Installing IIS or any other web server should be avoided, what we need is a self supporting process within a windows service on a basic windows XP installation + .NET.
Mono compatibility is a plus.
Thanks a million
Actually the easiest way is to use the built-in WCF stuff (.Net 3.5)... To do this you create a interface for your 'WCF' service that contains one or more methods that return Stream:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(UriTemplate = "/{*arguments}", Method="GET", BodyStyle=WebMessageBodyStyle.Bare)]
Stream Get(string arguments);
}
You can define several methods and arguments and let WFC do the work, or as the example above, push everything into a single method. The resulting implementation can access the full Uri and query parameters as follows:
public class ServiceType : IService
{
public Stream Get(string arguments)
{
UriTemplateMatch uriInfo = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
MemoryStream rawResponse = new MemoryStream();
TextWriter response = new StreamWriter(rawResponse, Encoding.UTF8);
response.Write("<html><head><title>Hello</title></head><body>");
response.Write("<b>Path</b>: {0}<br/>", arguments);
response.Write("<b>RequestUri</b>: {0}<br/>", uriInfo.RequestUri);
response.Write("<b>QueryParameters</b>: {0}<br/>", uriInfo.QueryParameters.ToString());
response.Write("</body></html>");
response.Flush();
rawResponse.Position = 0;
return rawResponse;
}
}
Now all you have to do is start up the WCF web/http self-host ...
static void Main()
{
Uri baseAddress = new Uri("http://localhost:8000/");
WebServiceHost svcHost = new WebServiceHost(typeof(ServiceType));
ServiceEndpoint svcEndpoint = svcHost.AddServiceEndpoint(typeof(IService),
new WebHttpBinding(), baseAddress);
svcEndpoint.Behaviors.Add(new WebHttpBehavior());
svcHost.Open();
Console.WriteLine("Press enter to quit...");
Console.ReadLine();
svcHost.Close();
}
NOTE: for the above example to work on Vista/Win7 you need to grant permissions with the following command-line:
netsh http add urlacl url=http://+:8000/ user=DOMAIN\USER
You can host the ASP.Net runtime in your own process. Rick Strahl has an old article about it called "Using the ASP.Net Runtime for extending desktop applications with dynamic HTML Scripts".
It should work fine for Windows XP, .Net 2.0 and up. If you combine this with the WCF code in #csharptest.net answer you should be able to use the power of ASP.Net pages and having an endpoint for it.
If you want a simple solutions, I would suggest you try Kayak.
From the site:
Kayak HTTP is a simple web server. It
listens for connections, creates an
in-memory representation of requests,
and allows you to easily generate
responses. It can be used in any C#
program. Your code loads Kayak into
its process spaceā€”not the other way
around!
It works well with mono also. Give it a shot! :)
Update
Your can also try aspnet serve
You could use UtilDev Cassini with your windows service. It is based on the original MS casini that is bult into visual studio and is free and redistributable.
If you were using Windows 7 you could use IIS7's Hostable Web Core feature to host a subset of IIS inside your service, without installing IIS7 itself.
What you are looking for is an embedded web server. While you can write your own, I suggest you check C# WebServer, an embedded web server written in C#.
Consider one of the Cassini builds or the new Hostable Web Core HWC

Web service cannot write to Event Log when called by anonymous user

SUMMARY: How to configure a web service such that writing to the Event Log is always possible (regardless of caller)?
DETAILS:
I have a web service which writes an entry to the Application Log. I established the event source for this by means of a little console application and I think I understand that part of things. When I test this WS, I see I am successfully writing my entry to the Event log.
The virtual directory which hosts this WS does NOT allow anonymous access and is configured for Integrated Windows Auth only.
I have a web client application that calls this Webservice. When the web client site is configured for Integrated Windows Auth only, calls to the Webservice result in logging as desired.
Yet, if I change the web client site to allow anonymous access then the Webservice attempt to log results in an InvalidOperationException. I ignore it but it would be nice to know how to get logging in the webservice regardless of how it is called. Here is a bit of my code:
public FileService()
{
try
{
if (!EventLog.SourceExists(g_EventSource))
EventLog.CreateEventSource(g_EventSource, g_EventLog);
System.Security.Principal.WindowsIdentity UserIdentityInfo;
UserIdentityInfo = System.Security.Principal.WindowsIdentity.GetCurrent();
string AuthType = UserIdentityInfo.AuthenticationType;
if (AuthType == "Kerberos")
{ engineWSE.Credentials = System.Net.CredentialCache.DefaultCredentials; }
else
{ engineWSE.Credentials = new System.Net.NetworkCredential("u", "p", "domain"); }
EventLog.WriteEntry(g_EventSource,
"Caller: " + UserIdentityInfo.Name +
" AuthType: " + UserIdentityInfo.AuthenticationType,
EventLogEntryType.Information, 1);
}
catch (InvalidOperationException e)
{
// do nothing to ignore: "Cannot open log for source 'myAppSourceName'. You may not have write access."
}
}
The example in the constructor above is sort of contrived for here (I am mainly interested in being able to write out info related to errors in the web service).
I hope there is a way to configure the web service virtual directory (or the code within) so that logging is possible regardless of how it got called.
Network Service is allowed to write to the Event Log, but not create an event source. you could give permissions to HKLM\SYSTEM\CurrentControlSet\Services\Eventlog\ to allow it to create - but if you've already created it at install time, there's no need.
It's possible that it's failing on the SourceExists as well - since that requires enumerating the same registry key. I'd probably just remove the SourceExists/Create check and trust that it's there - if you're anonymous, you can't create it anyway.
You should also check your web.config.
If IIS is set to anonymous and web.config is set to windows / impersonate. Then it will be the anonymous IIS user that is trying to write to the event log.

Categories

Resources