Web-service technologies cross domain - c#

Recently I've been trying to implement a web service. I started off trying to use the "Web API" technology in C#.
The end goal is to have a web service that connects to a SQL-Server database and can be called by other sites, sat on different domains.
The web service takes the request, connects to the database and serves back HTML (can be as a string inside a JSON object...etc). The client site then displays this HTML, gets input from the user and then sends this data back to the web service to save in the database.
There seems to be a problem with "Web API" when the calls are cross domain. The same-origin policy prevents us calling Cross-Domain. I have read into CORS, but believe it is not compatible with IE8, which is a big blocker for us.
Most of my knowledge and all of our sites are ASP.net C#.
Does anybody have any suggestions on how this can be achieved?
Thanks.

I haven't use Web API , but to allow cross domain calls to web service you may try adding it to the web.config file.It will allow HTTP GET / POST requests
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>

SAMPLE REQUEST:
$.ajax({
url: "http://yoururl",
type: "GET",
data: "yourdata",
dataType: "jsonp",
success: function (response) {
//do something;
}
});

We've resolved our issue by using a WCF service.

Related

proper implementation of "windows" authentication in web api?

I've created a Web Api 2 app which will only be used on the corporate network. I've read about Windows authentication in Web API so it seems to be possible. But I need to figure out the proper implementation for this. I've included the following xml in my Web.config:
<system.web>
<authentication mode="Windows" />
</system.web>
I seem to remember some type of event hook in old school webforms app. Something like BeginRequest() where a security check could be made before rendering a page. I included the following line of code as the first line in one of my controller methods but the returned value appears to just be an empty object without any meaningful info:
var identity = HttpContext.Current.User.Identity as WindowsIdentity;
Does Web API 2 support Windows authentication? Am I missing a step? Should Windows authentication work if I submit a general request from Postman for testing? I also tried this code but got a similar empty object:
var x = RequestContext.Principal;
I vaguely recall an IIS setting like "Enable Integrated Security." Can you please specify the exact setting? And would I be able to accomplish this if I'm running the app on IIS Express?
UPDATE
I followed the steps for IIS Express mentioned in one of the answers below but the code samples that I provided in my original post still didn't get a populated user object. I also updated applicationhost.config file to turn off anonymous authentication:
<anonymousAuthentication enabled="false" userName="" />
After I made that updated I resubmitted my test request via Postman but I get the following error:
<h3>HTTP Error 401.2 - Unauthorized</h3>
<h4>You are not authorized to view this page due to invalid authentication headers.</h4>
</div>
<div class="content-container">
<fieldset>
<h4>Most likely causes:</h4>
<ul>
<li>No authentication protocol (including anonymous) is selected in IIS.</li>
<li>Only integrated authentication is enabled, and a client browser was used that does not support integrated authentication.</li>
<li>Integrated authentication is enabled and the request was sent through a proxy that changed the authentication headers before they reach the Web server.</li>
<li>The Web server is not configured for anonymous access and a required authorization header was not received.</li>
<li>The "configuration/system.webServer/authorization" configuration section may be explicitly denying the user access.</li>
</ul>
</fieldset>
</div>
<div class="content-container">
<fieldset>
<h4>Things you can try:</h4>
<ul>
<li>Verify the authentication setting for the resource and then try requesting the resource using that authentication method.</li>
<li>Verify that the client browser supports Integrated authentication.</li>
<li>Verify that the request is not going through a proxy when Integrated authentication is used.</li>
<li>Verify that the user is not explicitly denied access in the "configuration/system.webServer/authorization" configuration section.</li>
<li>Check the failed request tracing logs for additional information about this error. For more information, click
here.
</li>
</ul>
</fieldset>
</div>
Do I need to configure my Postman request with some type of special header in order for this to work?
In addition to the previous answers, we also need to Pass credentials in cross-origin requests.
Server Side (Web API):
Set the SupportsCredentials property to true on the [EnableCors] attribute:
[EnableCors(origins: "http://exampleclient.com", headers: "*",
methods: "*", SupportsCredentials = true)]
Client Side (UI):
Set XMLHttpRequest.withCredentials to true.
jQuery:
$.ajax({
type: 'get',
url: 'http://www.example.com/api/auth',
xhrFields: {
withCredentials: true
}
Angular:
this.http.get('http://www.example.com/api/auth', { withCredentials: true }).subscribe((resp: any) => {
console.log(resp)
}
XMLHttpRequest:
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://www.example.com/api/auth');
xhr.withCredentials = true;
If you are using IIS Express, you need to update applicationhost.config file.
This is the file version of the IIS configuration tool where you can configure the web server itself. you can find this file in the following directory:
%userprofile%\documents\iisexpress\config\applicationhost.config
or
%userprofile%\my documents\iisexpress\config\applicationhost.config
When you find it, update it as:
<windowsAuthentication enabled="true">
<providers>
<add value="Negotiate" />
<add value="NTLM" />
</providers>
</windowsAuthentication>
For IIS:
Select your Application
Double Click - 'Authentication'
Enable Windows Authentication
Restart IIS Server
Check this for more details
Windows authentication that uses the local domain user and that is intended for intranet sites.
Example :
I implemented a TestAuthentication method/action with a fixed route path. For the demo I do not include Authorize attributes yet. The code checks the User property of the ApiController. This contains the same data as Thread.CurrentPrincipal or HttpContext.Current.User. Make sure Anonymous Authentication in IIS is disabled otherwise the Identity.Name will be empty.
public class WinAuthController : ApiController
{
[HttpGet]
[Route("api/testauthentication")]
public IHttpActionResult TestAutentication()
{
Debug.Write("AuthenticationType:" + User.Identity.AuthenticationType);
Debug.Write("IsAuthenticated:" + User.Identity.IsAuthenticated);
Debug.Write("Name:" + User.Identity.Name);
if (User.Identity.IsAuthenticated)
{
return Ok("Authenticated: " + User.Identity.Name);
}
else
{
return BadRequest("Not authenticated");
}
}
}
In Web.config file :
<system.web>
<authentication mode="Windows" />
</system.web>
In IE you can check the setting with Tools > Internet Options > Advanced and look for a setting Enable Windows Integrated Authentication. When you go to the tab Security and then Intranet and Custom Level, then you will find a setting at the bottom to specify if IE should logon automatically or prompt for the username and password.
Please visit below link, it has proper steps to follow for WEP API Windows authentication :
http://www.scip.be/index.php?Page=ArticlesNET38&Lang=EN
Below are the steps to configure windows authentication in web api for both local and server (IIS).
1) For Local:
a) To create a web api project in windows authentication mode, follow below steps:
After choosing ASP.Net Web Application, select Web API template and from the right side click Change Authentication button and select Windows Authentication.
b) For an existing web api project, just add the following lines in your applicationhost.config file.
<location path="YourProjectName">
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
</location>
2) For Server (IIS)
To run windows authentication after hosting the application in IIS just add following lines in your web.config file inside system.web node:
<authentication mode="Windows" />
<authorization>
<allow verbs="OPTIONS" users="?" />
<deny users="?" />
</authorization>
In both the cases, just use the following lines in your code that windows authentication is working properly:
if(User.Identity.IsAuthenticated)
{
//do work
}

Enable CORS on Specific URL in ASP.NET Web Forms

I'm not a backend developer, so I apologize ahead of time if I do not provide enough information. I am just trying to find some resources that will help my backend developer understand what I am trying to do.
I am trying to make an AJAX GET request to an rss feed inside of web application that was built using ASP.NET Web Forms. However, the request gets blocked because of Cross Origin Security. I want to enable CORS for the route that is associated with our RSS feed (/page/rss/{id}).
I was able to enable CORS in our webconfig using:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" values="*" />
<add name="Access-Control-Allow-Methods" values="GET" />
<add name="Access-Control-Allow-Headers" values="Content-Type" />
</customHeaders>
</httpProtocol>
But, that enables it for the entire project which is not what I want. Our routes are defined in an XML file like this:
<namespace.routing>
<routings>
<route name="publishedPage" url="page/{PageName}" page="~/Default.aspx" />
</routings>
<defaults>
<default url="http://blog.example.com" domain="example.com" page="page/homepage" />
</defaults>
</namespace.routing>
So, how would one go about enabling CORS on a specific path in ASP.NET Web Forms? If someone could point me in the direction of some resources that would help us that would be great. If you need anymore information I'm happy to provide it. Thanks!
I'm not sure how you are returning your rss endpoint, but if you have access to the HttpContext object, you can use it to supply the CORS headers directly.
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "*");
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Methods", "Get");
HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Headers", "Content-Type");
Depending on how old your app is, you might need to use AddHeader instead of AppendHeader.

Asp.net MVC5 with Angular 2 configuration

I'm beginner in Angular 2. I'm creating Angular project using Angular CLI. I'm separately creating asp.net MVC Web api project.
Using angular CLI to ng serve command start this service: localhost:4200
MVC web api start this service: localhost:65320
When i use Angular http get request to download data from localhost:65320/api/myservice, Cross origin problem occurred. Because angular project using different url. But i'm adding header to Access-Control-Allow-Origin=* problem solved.
But when i use http post request always return 405 method not allowed problem occurred
Question:
How to allow cross origin post request in web api controller?
Or how to configure Angular CLI created project work together with MVC project?
Correct Answer:
Web api cross origin problem solved following this article:
https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors suggest by #chandermani
You can enable CORS in Web API in two different ways:
Using Microsoft.AspNet.WebApi.Cors: follow tutorial https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api as Chandermani pointed out.
Add the following to your system.webServer element in your web.config:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>

How to debug/trace System.Web.Services.Protocols.SoapHttpClientProtocol.invoke (from Windows mobile)?

I am trying to call web service from C# application but I am getting exception:
InvalidOperationException
client found response content type of 'text/html; charset=utf-8', but expected 'text/xml'
How can I see the request and reponse messages un URL? My service runs on Desktop, but client runs on Windows Mobile CE 6.x, mobile device is connected to the Dektop using usb. Probabily that is the reason why I don't see the HTTP traffic in Wireshark or Fiddler (I have tried both). The service works - I can check it using Postman (method returns correct and meaningful result XML).
You can turn on the debug on some of the libraries that internally make the HTTP calls (in my case, they are HTTPS, so inspecting via wireshark is impossible).
You should add to your app.config:
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.Net" tracemode="protocolonly" maxdatasize="1024">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener"
initializeData="trace.log"/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose"/>
</switches>
</system.diagnostics>
This will add a trace.log where your exe runs. If you don't know where your service is running, you should be able to put a non-relative path.
Also, this adds the same logs when running the code inside Visual Studio, in the output window (not the output console).
P.S.: You can change the log level to "Information" if you just need the headers of the request and responses and information on opening and closing connection.
Okay, this is going to sound weird, but are you using Default Document within IIS? I know this probably shouldn't be the case, but when I set up a default document for my web service's site, and pointed my ServiceReference to the shortened address, it was able to run... but only locally. Otherwise, I'd get that same "Html instead of XML" error.
The fix in my case was to no longer refer to the shortened URL in the service reference, and type out the full URL (aka, not using the default document property for the site.)
The easiest and best way to debug a SOAP client is to create a SOAP extension that logs the SOAP messages sent to and from a Web service or Web service client.
Codeproject has a good tutorial how to do this properly: Efficient Tracing Using SOAP Extensions in .NET
And here is a shorter MSDN article: How to: Implement a SOAP Extension
There are also commercial SOAP Debuggers out that are worth the money, like the XML Spy SOAP Debugger or SOAPSonar which does validation and invocation.
BTW: If you would use PHP or Java you would basically use the same approach.

The test form is only available for requests from the local machine

Why is it that for some of my web services, I get test forms, so I can see the generated XML data, but for other web services, I get a message saying "The test form is only available for requests from the local machine."?
Both times, I am connecting to the URL of the web-service from a client side browser and all web services are created with C#, .NET 3.5.
I googled for "The test form is only available for requests from the local machine."
There were many results, and the consensus is to add these nodes to the web.config file of the web service. I haven't tried this solution yet, but you can check to see if your web services that shows the test form remotely has this that have these nodes in the web.config. Or, you can add it to the web services that give this message and see if the test form starts appearing remotely.
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>
Here are some of the search results
Stack Overflow: The test form is only available for requests from the local machine.
GeeksWithBlogs (archived on the Internet Wayback Machine): "The test form is only available for requests from the local machine"
Microsoft support: INFO: HTTP GET and HTTP POST Are Disabled by Default

Categories