How to make your first WebAPI2 Project

With the introduction of OWIN  and self hosting, microsoft has really opened a lot of possible doors for developers and application users. This post is targetted to have an OWIN application hosted in Windows Service. Also we would be configuring the SSL for the Site.

Creating a Windows Services Project

This is pretty straightforward. In visual Studio, Create new project and select Windows Service as project. This will add a project with default Service “Service1”. Rename to whatever the name expected. Continue reading “How to make your first WebAPI2 Project”

Using ASMX webservices with HttpWebRequest in c# 4.0

If you want to call a .NET 4.0 C# web service, without using the WSDL or “Add Service Reference” in Microsoft Visual Studio 2015, you can use the following functions written in c#:

/// <summary>
/// Execute a Soap WebService call
/// </summary>
public override void Execute()
{
HttpWebRequest request = CreateWebRequest();
XmlDocument soapEnvelopeXml = new XmlDocument();
soapEnvelopeXml.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<soap:Body>
<HelloWorld3 xmlns=""http://tempuri.org/"">
<parameter1>test</parameter1>
<parameter2>23</parameter2>
<parameter3>test</parameter3>
</HelloWorld3>
</soap:Body>
</soap:Envelope>");
using (Stream stream = request.GetRequestStream()) 
{ 
soapEnvelopeXml.Save(stream); 
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream())) 
{ 
string soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
} 
}
}
/// <summary>
/// Create a soap webrequest to [Url]
/// </summary>
/// <returns></returns>
public HttpWebRequest CreateWebRequest()
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(@"http://dev.nl/Rvl.Demo.TestWcfServiceApplication/SoapWebService.asmx"); 
webRequest.Headers.Add(@"SOAP:Action"); 
webRequest.ContentType = "text/xml;charset=\"utf-8\""; 
webRequest.Accept = "text/xml"; 
webRequest.Method = "POST"; 
return webRequest; 
}

Result

<?xml version=”1.0″ encoding=”utf-8″?><soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”><soap:Body><HelloWorld3Response xmlns=”http://tempuri.org/”><HelloWorld3Result>test</HelloWorld3Result></HelloWorld3Response></soap:Body></soap:Envelope>

 

You can use complex types in you’re request. I use fiddler to get the contents of the soap envelope.

How to create a JSON POST request from a GET method

Let’s say you find a security hole in your system from old developers – leaving one of your webservices exposed:

http://mywebservice/MyService.asmx/SendEmail?Username=1234&Password=1224!&EmailFrom=no-reply@carra-lucia-ltd.co.uk&EmailTo=carra_lucia@hotmail.com&Subject=MySubject&Message=Dear%20Administrator,test%20mail%20here

Now how would you transform this into a POST string with JSON?


  var myURL = "http://mywebservice/MyService.asmx/SendEmail";
        var dataToUse = $.parseJSON('{"Username": "1234","Password":"1224!","EmailFrom":"no-reply@carra-lucia-ltd.co.uk","EmailTo":"carra_lucia@hotmail.com","Subject":"MySubject","Message":"' + msg + '"}');
        $.ajax({
            type: "POST",
            url: myURL,
            contentType: "application/json; charset=utf-8",
            dataType: "jsonp",
            data: dataToUse,
            crossDomain: true,
            success: function (response) {
                //email was sent
                alert("Email has been sent successfully!");
            },
            error: function (jqXHR, error, errorThrown) {
                if (jqXHR.status && jqXHR.status == 400) {
                    alert(jqXHR.responseText);
                } else {
                    alert("Something went wrong. We could not send your email.");
                }
            }
        });

MySubject

Using jQuery ajax to call asmx webservice methods

One imprtant distinction is what I mean by a JSON object and JSON format.  A JSON object is an object that can be used by javascript

var o = {data: 'value'};
alert (o.data); // this works as o is an object

JSON format is simply a literal string that can be turned into a JSON object if we parse it

var f = "{data: 'value'}";
alert (f.data); // this won't work as f is just a string and string doesn't have a data property

The following code calls a webservice that has three different SayHello functions.

[WebMethod]
public string SayHello(string firstName, string lastName)
{
    return "Hello " + firstName + " " + lastName;
}

[WebMethod]
public string SayHelloJson(string firstName, string lastName)
{
    var data = new { Greeting = "Hello", Name = firstName + " " + lastName };

    // We are using an anonymous object above, but we could use a typed one too (SayHello class is defined below)
    // SayHello data = new SayHello { Greeting = "Hello", Name = firstName + " " + lastName };

    System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();

    return js.Serialize(data);
}

[WebMethod]
public SayHello SayHelloObject(string firstName, string lastName)
{
    SayHello o = new SayHello();
    o.Greeting = "Hello";
    o.Name = firstName + " " + lastName;

    return o;
}

“SayHello” returns a string

“SayHelloJson” returns a string that is an object in JSON format

“SayHelloObject” returns an object.  The SayHello class is here

public class SayHello
{
    public string Greeting { get; set; }
    public string Name { get; set; }
}

I have added the comments inline on the code, but the examples cover calling all three types of webservice method, and they also cover getting simple text back and getting JSON objects back, and also sending parameters in form encoded formats and also JSON formats.

Enjoy

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="test.aspx.cs" Inherits="WebTest.ajax.test" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
        http://../Scripts/jquery-1.4.1.js
</head>
<body>
    <form id="form1" runat="server">
    

Example A

Example B

Example C

Example D

Example E
/* SayHello returns a string SayHelloJson returns a string that is an object in JSON format SayHelloObject returns an object [WebMethod] public string SayHello(string firstName, string lastName) { return "Hello " + firstName + " " + lastName; } [WebMethod] public string SayHelloJson(string firstName, string lastName) { var data = new { Greeting = "Hello", Name = firstName + " " + lastName }; // We are using an anonymous object above, but we could use a typed one too (SayHello class is defined below) // SayHello data = new SayHello { Greeting = "Hello", Name = firstName + " " + lastName }; System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer(); return js.Serialize(data); } [WebMethod] public SayHello SayHelloObject(string firstName, string lastName) { SayHello o = new SayHello(); o.Greeting = "Hello"; o.Name = firstName + " " + lastName; return o; } public class SayHello { public string Greeting { get; set; } public string Name { get; set; } } */ $(document).ready(function () { // SayHello returns a string we want to display. Examples A, B and C show how you get the data in native // format (xml wrapped) as well as in JSON format. Also how to send the parameters in form-encoded format, // JSON format and also JSON objects. To get JSON back you need to send the params in JSON format. // Example A - call a function that returns a string. // Params are sent as form-encoded, data that comes back is text $.ajax({ type: "POST", url: "MyWebService.asmx/SayHello", data: "firstName=Aidy&lastName=F", // the data in form-encoded format, ie as it would appear on a querystring //contentType: "application/x-www-form-urlencoded; charset=UTF-8", // if you are using form encoding, this is default so you don't need to supply it dataType: "text", // the data type we want back, so text. The data will come wrapped in xml success: function (data) { $("#searchresultsA").html(data); // show the string that was returned, this will be the data inside the xml wrapper } }); // Example B - call a function that returns a string. // Params are sent in JSON format, data that comes back is JSON $.ajax({ type: "POST", url: "MyWebService.asmx/SayHello", data: "{firstName:'Aidy', lastName:'F'}", // the data in JSON format. Note it is *not* a JSON object, is is a literal string in JSON format contentType: "application/json; charset=utf-8", // we are sending in JSON format so we need to specify this dataType: "json", // the data type we want back. The data will come back in JSON format success: function (data) { $("#searchresultsB").html(data.d); // it's a quirk, but the JSON data comes back in a property called "d"; {"d":"Hello Aidy F"} } }); // Example C - call a function that returns a string. // Params are sent as a JSON object, data that comes back is text $.ajax({ type: "POST", url: "MyWebService.asmx/SayHello", data: { firstName: 'Aidy', lastName: 'F' }, // here we are specifing the data as a JSON object, not a string in JSON format // this will be converted into a form encoded format by jQuery // even though data is a JSON object, jQuery will convert it to "firstName=Aidy&lastName=F" so it *is* form encoded contentType: "application/x-www-form-urlencoded; charset=UTF-8", dataType: "text", // the data type we want back, so text. The data will come wrapped in xml success: function (data) { $("#searchresultsC").html(data); // show the data inside the xml wrapper } }); // SayHelloJson returns a .net object that has been converted into JSON format. So the method still return a // string, but that string is an object in JSON format. It is basically an object within an object. We still // get the "d" property back as in Example B, but "d" is an object represented in JSON format itself. // Example D - call a function that returns a string that is an object in JSON format. // Params are sent in JSON format, data that comes back is a string that represents an object in JSON format $.ajax({ type: "POST", url: "MyWebService.asmx/SayHelloJson", data: "{ firstName: 'Aidy', lastName: 'F' }", contentType: "application/json; charset=utf-8", dataType: "json", success: function (data) { var myData = JSON.parse(data.d); // data.d is a JSON formatted string, to turn it into a JSON object // we use JSON.parse // now that myData is a JSON object we can access its properties like normal $("#searchresultsD").html(myData.Greeting + " " + myData.Name); } }); // SayHelloObject returns a typed .net object. The difference between this and Example D is that in Example D // the "d" property is an object in JSON format so we need to parse it to make it a JSON object. Here the // "d" property is already an actual JSON object so no need to parse it. // Example E - call a function that returns an object. .net will serialise the object as JSON for us. // Params are sent in JSON format, data that comes back is a JSON object $.ajax({ type: "POST", url: "MyWebService.asmx/SayHelloObject", data: "{ firstName: 'Aidy', lastName: 'F' }", contentType: "application/json; charset=utf-8", dataType: "json", success: function (data) { var myData = data.d; // data.d is a JSON object that represents out SayHello class. // As it is already a JSON object we can just start using it $("#searchresultsE").html(myData.Greeting + " " + myData.Name); } }); }); </form> </body> </html>

.NET Webservice still returning XML instead of Json

I was trying to call a webservice method through the jquery ajax metod and guess what: I was always getting an xml response

$.ajax(
{
type: “POST”,
url: http://localhost:50080/ElearningWebApplication/ChatWebService.asmx/InserMessage,
data: “{}”,
contentType: “application/json; charset=utf-8”,
dataType: “json”,
crossDomain: true,
success: function (response) {
//email was sent
alert(“Email has been sent successfully!”);
},
error: function (jqXHR, error, errorThrown) {
if (jqXHR.status && jqXHR.status == 400) {
alert(jqXHR.responseText);
} else {
alert(“Something went wrong. We could not send your email.”);
}
}

}

);

 I included the correct attributes to both the service and the method

[WebService(Namespace = http://www.action.gr/&#8221;)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class ChatWebService : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

          public string InsertMessage(string text, int roomID, int userID, string color, int toUserID)
{
…..
}
}

<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <system.webServer>
        <handlers>
            <add name="ScriptHandlerFactory"
                 verb="*" path="*.asmx"
                 type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                 resourceType="Unspecified" />
        </handlers>
    </system.webServer>
</configuration>

Final Checklist

  1. Did you specify type: “POST” in the ajax request? A security feature of ASP.NET web services that are JSON serialized through the ASP.NET AJAX extensions is that they must be requested in a specific way. This is an important deterrent against your services being used in XSS attacks.
  2. Did you specify contentType: “application/json; charset=utf-8” in the ajax request?
  3. Did you specify dataType: “json”in the ajax request?
  4. Does your .asmx web service include the [ScriptService]` attribute?
  5. Does your web method include the [ScriptMethod(ResponseFormat = ResponseFormat.Json)] attribute? (My code works even without this attribute, but a lot of articles say that it is required)
  6. Have you added the ScriptHandlerFactory to the web.config file in ?
  7. Have you removed all handlers from the the web.config file in in ?

Create SAP Web Service with SAP .Net Connector in 5 minutes

Author: Dennis Wang / Microsoft / EAS /SAP

What is SAP .NET Connector

  • SAP product. Based on Microsoft .NET Technology
  • Interact with SAP via RFC/SOAP
  • Fully integrated with Visual Studio.NET
  • Managed Code
  • Generates C# Proxy Classes for any .NET application integrations
  • Supports RFC and SOAP
  • Supports qRFC, tRFC
  • Supports asynchronous SOAP calls
  • RFC client or RFC server

SAPNET

Feature of Web Service

  • It is ASP.Net Web Service
  • Hosted by IIS. Using HTTP protocol
  • Secure: SSL for connection. NTLM for authentication. Role base authorization.
  • Single sign via NTLM GSSAPI
  • Platform Neutral. Can be accessed via http protocol.
  • Strong versioning via XML Namespace

Steps to Create Web Service for RFC_Customer_Get

  • Create a C# project for ASP.Net Web Service
  • Generate SAP Proxy via SAP .Net Proxy Generator for RFC_Customer_Get
  • Open Proxy1.cs and change the following line
  • public void Rfc_Customer_Get(…) to public virtual void Rfc_Customer_Get (…)
  • Open Service1.asmx and do the following modification
  • public class Service1 : SAPProxy1
  • public override void Rfc_Customer_Get (…)
  • Add this code in this method
  • this.Connection = SAP.Connector.SAPConnectionPool.GetConnection (MyConnectionString);
  • base.Rfc_Customer_Get(Kunnr,Name1, ref Customer_T);
  • Compile the code and you have the web service for this RFC.

How SAP Single Sign On work under ASP.Net Web Service

singlesign

Set up single sign on for web service

IIS Configuration

  • Disable anonymous access
  • Set up Windows Integrated Authentication

Web Service Configuration
Generate encrypted user name and password via aspnet_setreg.exe program. This value will then be set up in registry. Here we assume the user name is SAPCMDEV
Add the following line in Web.Config

<identity impersonate=”true” sername=”registry:HKLMSoftwareSapWebServiceIdentityASPNET_SETREG,sername”
password=”registry:HKLMSoftwareSapWebServiceIdentityASPNET_SETREG,password” /> 
GSS Library
  • Requires on the server where Web Service is located.
  • Copy the GSSNTLM.DLL to c:windowssystem32
  • If the GSSNTLM.DLL was copied to a folder other then within the environment search path, you need to add the following line in system environment SNC_LIB=”file pathGSSNTLM.dll”
  • Make sure to replace the gssapi32.dll with this GSSNTLM.dll if the old gssapi32.dll exists. The old gssapi32.dll does not work.
  • Create Entry in Table SNCSYSACL via SNC0
  • This table contains a list of trusted domain accounts or SNC.
  • Start SAP and run SNC0
  • Make sure to enable the RFC/CPIC/Ext ID options

singlesignon

  • Make sure all users who access SAP will have their User Accounts in USRACL or via SU01
  • Mapping external users into SAP users
  • Run SM30 and table VUSREXTID
  • Value: Work Area=NT.
  • Value: External ID = MYDomaindennisw
  • Program The Connection String with the following value:
  • SNC_MODE=1;
  • SNC_PARTNERNAME=”p:” + System.Security.Principal.WindowsIdentity.GetCurrent().Name; ‘ Web Service Process Account
  • EXTIDDATA=User.Identity.Name; ‘Caller credential
  • EXTIDTYPE=“NT”;

infopath

How does InfoPath 2003 connect to SAP?

  • Utilize SAP RFC and BAPI.
  • Generate RFC/BAPI proxy by using SAP .Net Connector
  • Create Web Service Wrapper around the proxy
  • Hosting/Publish the web service via WSDL
  • InfoPath Consume the web service
InfoPath 2003 SDK
–Available on microsoft.com under downloads
InfoPath 2003, Technical Webcasts, Technical White Papers, Development Guides
–MSDN
Visit http://microsoft-sap.com for information on:
–SAP at Microsoft
–SAP .Net Connector
–Upcoming customer workshops

Securing Web Services With Username and Password (Custom SoapExtension)

Have you ever wanted to intercept a web service method because you wanted to maybe log it or even as we are about to do authenticate a user?  Did you know you can intercept any incoming SoapMessage that is sent to your web service?  This is all possible because of the SoapExtension class in .Net. Not only can you intercept the incoming message but you can do it within one of four stages:

  1. AfterDeserialize
  2. AfterSerialize
  3. BeforeDeserialize
  4. BeforeSerialize

This allows us a lot of flexibility obviously.  In our example we are going to work with the AfterDeserialize stage which is after the message has been sent across the wire and serialized into a SoapMessage object.  Since we will have a full blown SoapMessage object, we can inspect the headers of the SoapMessage and take care of authentication then.  Our end goal with taking this approach is to allow us to authenticate a user with a WebMethod simply by adding an authentication attribute to the WebMethod like this highlighted in bold.

    [WebMethod]
[SoapHeader(“CustomSoapHeader”)]
[AuthenticatonSoapExtensionAttribute] (magic here)

public int AddTwoNumbers(int x, int y)
{
return x + y;
}

You’ll notice in this example we do not have to remember to call the code to authenticate the user manually as we saw in the previous article.  Instead by adding the attribute to the method it knows to call the authentication method.  To do this we need to first create a custom object that extends SoapExtensionAttribute and then another that extends SoapExtension.

Create a Custom SoapExtensionAttribute

In order to have the method call our custom SoapExtension we need to create an object that extends SoapExtensionAttribute.  It is a farily simple class with two overridden properties.  Here’s the code:

 [AttributeUsage(AttributeTargets.Method)]
public class AuthenticatonSoapExtensionAttribute : SoapExtensionAttribute
{
private int _priority;
public override int Priority
{
get { return _priority; }
set { _priority = value; }
}

public override Type ExtensionType
{
get { return typeof(AuthenticatonSoapExtension); }
}
}

You’ll notice about the only thing of real substance is the Extension type property which simply returns to us our custom extension.

Create a Custom SoapExtension

The last piece to pull this all together is a custom class which extends the SoapExtension class.  In this class we are going to write the code that does the actual authentication.  We are going to check for the AfterDeserialize stage and then first make sure we have a valid SoapHeader.   Once we do that we are going to call the static validation method and pass in the SoapHeader as we did above.

 /// <summary>
/// Custom SoapExtension that authenticates the method being called.
/// </summary>

public class AuthenticatonSoapExtension : SoapExtension
{
/// <summary>
/// When overridden in a derived class, allows a SOAP extension to initialize data specific to an XML Web service method using an attribute applied to the XML Web service method at a one time performance cost.
/// </summary>
/// <param name=”methodInfo”></param>
/// <param name=”attrib”></param>

public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attrib)
{
return null;
}
/// <summary>
/// When overridden in a derived class, allows a SOAP extension to initialize data specific to a class implementing an XML Web service at a one time performance cost.
/// </summary>
/// <param name=”WebServiceType”></param>

public override object GetInitializer(Type WebServiceType)
{
return null;
}

/// <summary>
/// When overridden in a derived class, allows a SOAP extension to initialize itself using the data cached in the GetInitializer method.
/// </summary>
/// <param name=”initializer”></param>

public override void Initialize(object initializer)
{
}

/// <summary>
/// After the message is deserialized we authenticate it.
/// </summary>
/// <param name=”message”></param>
public override void ProcessMessage(SoapMessage message)
{
if (message.Stage == SoapMessageStage.AfterDeserialize)
{
Authenticate(message);
}
}

public void Authenticate(SoapMessage message)
{
ServiceAuthHeader header = message.Headers[0] as ServiceAuthHeader;
if (header != null)
{
ServiceAuthHeaderValidation.Validate(header);
}
else
{
throw new ArgumentNullException(“No ServiceAuthHeader was specified in SoapMessage.”);
}
}

}

The method that we are really concerned with is the ProcessMessage which checks for the stage and then calls the Authenticate method.  This in turn calls our static validation method which checks for authentication.  At this point light bulbs should be going off!   Since we have a SoapMessage object do we not know which method is being called?  Yes!  Could we modify the ServiceAuthHeaderValidation to check for a database instead of hard coding things?  Yes!  Now you are starting to see where this could really go.   SoapExtensions are powerful and only limited to your imagination.

When I Test It, It Doesn’t Work, Why?

Once you get your SoapExtension in your solution setup and press F5 to debug it within Visual Studio  it will launch a new web server on a random port and bring you to your service.  You enter the parameters and submit the form and it by passes your validation.  Why!?

This is suppose to happen and here is why. If you go to the service invoked from VS through the browser interface it will not invoke the authentication and it isn’t suppose to either. The reason is you are not invoking the service via SOAP but rather just a standard POST from a form. Therefore, the SOAP extension is never going to fire. This should be disabled when you publish your web service to production as only SOAP messages should be allowed. If you have a case where you need to allow GET and POST calls then the method of a custom SoapExtension isn’t going to work.

As a benefit, Visual Studio builds the form for you automatically when you press F5 and allows you to pass parameters to the web method, but it does it via POST. If you invoke the web method from a console application or a real client making a SOAP call, you have to pass in the username and password.  I actually consider this behavior a feature.  If we didn’t use the SoapExtension to secure the method, we’d be forced to pass in username and password all the time which would mean we’d have to always call the secured web method from a test client.   Speaking from experience this isn’t fun.  Of course you should have Unit Tests for each web method anyway but it is really easy to pass in the params to a web form while debugging.

I hope you find this useful and now don’t feel so daunted because your team leader asked you how you were going to authenticate web service methods via a database.  The only thing left is for you to implement your required features.  Of course, if you are on an Intranet, instead of using username and password as we did in the previous post you could at the point of Authenticate(SoapMessage message) use the user’s integrated credentials and check for various groups in Active Directory or even using Enterprise Library Security Block.