MapPad app is growing

Hi, It’s been a while since I have posted anything. Just to let you know that MapPad project has grown significantly in the past year, lots of new functions have been added and you can get the app demo for free here.

The most recent update includes WMS and ArcGIS Server Tiled services support, you can add your own Google Maps overlay and improve your productivity even more:

http://mappadapp.com/adding-custom-wms-service

http://mappadapp.com/google-maps-overlays

Enjoy šŸ™‚

Advertisements

WCF 4.0 – Windows Authentication

I use the Windows Authentication very often in my everyday projects, so decided to write this article as it might be useful for you as well…

My aim was to create one web service with 2 endpoints having different HTTP methods available:

To achieveĀ that you canĀ use the WCF template available in VS 2010 as a start point:

1. Create new VS 2010 project using the Online Template (make sure .Net 4 is selected)

2. Modify the Service1.cs file replacing the original content with the code below:

Make sure that you have replace the WCF_Service_40 namespace with your original namespace.
As you can see we have added another contract class with methods available when user is authenticated.


using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;

namespace WCF_Service_40
{
// Start the service and browse to http://:/Service1/help to view the service's generated help page
// NOTE: By default, a new instance of the service is created for each call; change the InstanceContextMode to Single if you want
// a single instance of the service to process all calls.
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
// NOTE: If the service is renamed, remember to update the global.asax.cs file
public class Public_Service
{
// TODO: Implement the collection resource that will contain the SampleItem instances

[WebGet(UriTemplate = "")]
public List GetCollection()
{
// TODO: Replace the current implementation to return a collection of SampleItem instances
return new List() { new SampleItem() { Id = 1, StringValue = "Hello" } };
}

}

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class Admin_Service
{
// TODO: Implement the collection resource that will contain the SampleItem instances

[WebGet(UriTemplate = "")]
public List GetCollection()
{
// TODO: Replace the current implementation to return a collection of SampleItem instances
return new List() { new SampleItem() { Id = 1, StringValue = "THis message can be seen only by authentificated users." } };
}

[WebInvoke(UriTemplate = "", Method = "POST")]
public SampleItem Create(SampleItem instance)
{
// TODO: Add the new instance of SampleItem to the collection
throw new NotImplementedException();
}

[WebGet(UriTemplate = "{id}")]
public SampleItem Get(string id)
{
// TODO: Return the instance of SampleItem with the given id
throw new NotImplementedException();
}

[WebInvoke(UriTemplate = "{id}", Method = "PUT")]
public SampleItem Update(string id, SampleItem instance)
{
// TODO: Update the given instance of SampleItem in the collection
throw new NotImplementedException();
}

[WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
public void Delete(string id)
{
// TODO: Remove the instance of SampleItem with the given id from the collection
throw new NotImplementedException();
}

}
}

3. Open Global.asax.cs file and replace it content to:

In the code below we are creating custom WebServiceHostFactoryclass. When registering route we can now add parameter ‘true’ or ‘false’ depending if we want the security to be turned on or off.


private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("soapService", new SoapServiceHostFactory(), typeof(Public_Service)));
RouteTable.Routes.Add(new ServiceRoute("restService", new CustomWebServiceHostFactory(false), typeof(Public_Service)));
RouteTable.Routes.Add(new ServiceRoute("adminService", new CustomWebServiceHostFactory(true), typeof(Admin_Service)));
}

Full code:


using System;
using System.ServiceModel.Activation;
using System.Web;
using System.Web.Routing;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.Web.Configuration;
using System.Configuration;

namespace WCF_Service_40
{
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}

private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("soapService", new SoapServiceHostFactory(), typeof(Public_Service)));
RouteTable.Routes.Add(new ServiceRoute("restService", new CustomWebServiceHostFactory(false), typeof(Public_Service)));
RouteTable.Routes.Add(new ServiceRoute("adminService", new CustomWebServiceHostFactory(true), typeof(Admin_Service)));

}
}

public class SoapServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
host.AddServiceEndpoint(serviceType, new BasicHttpBinding(), "soap");
return host;

}

}

public class CustomWebServiceHostFactory : WebServiceHostFactory
{

private bool security_enabled;
public CustomWebServiceHostFactory(bool security_enabled)
{
this.security_enabled = security_enabled;
}

protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
WebServiceHost host = (WebServiceHost)base.CreateServiceHost(serviceType, baseAddresses);

if (security_enabled == false)
{
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });

ServiceEndpoint xml_endpoint = host.AddServiceEndpoint(serviceType, new WebHttpBinding { }, "XML");
xml_endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Bare, HelpEnabled = true, DefaultOutgoingResponseFormat = WebMessageFormat.Xml });

ServiceEndpoint json_endpoint = host.AddServiceEndpoint(serviceType, new WebHttpBinding { }, "JSON");
json_endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Bare, HelpEnabled = true, DefaultOutgoingResponseFormat = WebMessageFormat.Json });

}
else
{
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });

ServiceCredentials serviceCredential = host.Description.Behaviors.Find();
if (serviceCredential == null)
{
serviceCredential = new ServiceCredentials();
serviceCredential.WindowsAuthentication.AllowAnonymousLogons = false;
serviceCredential.WindowsAuthentication.IncludeWindowsGroups = true;
host.Description.Behaviors.Add(serviceCredential);
}

ServiceEndpoint xml_endpoint = host.AddServiceEndpoint(serviceType, new WebHttpBinding { Security = new WebHttpSecurity { Mode = WebHttpSecurityMode.TransportCredentialOnly, Transport = new HttpTransportSecurity { ClientCredentialType = HttpClientCredentialType.Windows, ProxyCredentialType = HttpProxyCredentialType.Windows } } }, "XML");
xml_endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Bare, HelpEnabled = true, DefaultOutgoingResponseFormat = WebMessageFormat.Xml });

ServiceEndpoint json_endpoint = host.AddServiceEndpoint(serviceType, new WebHttpBinding { Security = new WebHttpSecurity { Mode = WebHttpSecurityMode.TransportCredentialOnly, Transport = new HttpTransportSecurity { ClientCredentialType = HttpClientCredentialType.Windows, ProxyCredentialType = HttpProxyCredentialType.Windows } } }, "JSON");
json_endpoint.Behaviors.Add(new WebHttpBehavior { DefaultBodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Bare, HelpEnabled = true, DefaultOutgoingResponseFormat = WebMessageFormat.Json });

}
return host;

}

}

}

4. Try to access the adminService using debugging:

You should be getting the error from the picture below:

4. To add the windows authenticationĀ publish your WCF Service on IIS 7 (Windows Vista, 7 Home edition do not support the Windows authentification – you have to have the proffesional version of the operating system to enable it).

5. Add Blank ‘AdminService’ folder to your deployment folder and enable the windows authentication on it as shown on the picture below:

6. If you still cannot get the AdminServis URI working try to edit the C:\Windows\System32\inetsrv\config\applicationHost.config file changing overrideModeDefault value for Anonymus and Windows authentication type as shown below.

 

7. When it’s configured properly you should be able to access both endpoint using different authentification method.