How to publish a WCF Rest Webservice? - c#

My App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1">
<endpoint address="http://localhost/webservice"
binding="webHttpBinding"
contract="WcfJsonRestService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I published my webservice to the http://localhost/webservice target but when I openhttp://localhost/webservice/ in my browser I get this:
localhost - /webservice/
[To Parent Directory]
11/9/2015 10:30 AM <dir> bin
11/9/2015 11:23 AM 58 WcfJsonRestService.Service1.svc
11/9/2015 11:22 AM 481 Web.config
This works well in debug mode. I just do http://localhost/webservice/getUsers and I receive a list of users. The problem occurs when I publish the webservice to the IIS because http://localhost/webservice/getUsers returns HTTP Error 404.0 - Not Found.
Any suggestions?

You can try this.
You can configure anonymous authentication by using the default
anonymous user account (IUSR), or you can set up a local user account
for anonymous users.
In Features View of IIS Manager, double-click Authentication.
On the Authentication page, select Anonymous Authentication.
In the Actions pane, click Edit to set the security principal (user credentials) under which anonymous users will connect to the site.
In the Edit Anonymous Authentication Credentials dialog box, select one of the following options:
If you want to configure a specific user account that IIS uses to access your site or application, select Specific user. Then click Set to open the Set Credentials dialog box, and enter a user name and password for the identity. Then click OK.
If you want IIS processes to run by using the account that is currently specified on the property page for the application pool, select Application pool identity. By default, this identity is the IUSR account. (Important: If you use the IUSR account, you grant anonymous users all the internal network access associated with that account.)
Click OK to close the Edit Anonymous Authentication Credentials dialog box.
You can use this link as reference.

Related

Can't resolve/use System.ServiceModel.Security.WSTrustServiceContract as service name

I have a token issuer WCF service which is using Microsoft.IdentityModel (WIF 3.5) that I need to upgrade to System.IdentityModel (.NET 4.5). The problem is that I can't change the original name of the service , Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract, to it's newer counterpart, System.ServiceModel.Security.WSTrustServiceContract. For some reason it's not recognized by IntelliSense:
The blue squiggly line error is:
The 'name' attribute is invalid - The value 'System.ServiceModel.Security.WSTrustServiceContract' is invalid according to its datatype 'serviceNameType'
I do have assembly references to System.ServiceModel and System.IdentityModel in <assemblies> node.
Even when I ignore the IntelliSense error and run the service and access it using browser I'm getting this metadata error:
Metadata publishing for this service is currently disabled.
Metadata publishing is enabled so I think it's because of the name problem of the service.
Also I'm getting this error from the VS.NET WCF test client:
Error: Cannot obtain Metadata from http://localhost:49178/Services/Issuer.svc
If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.
WS-Metadata Exchange Error
URI: http://localhost:49178/Services/Issuer.svc
Metadata contains a reference that cannot be resolved: 'http://localhost:49178/Services/Issuer.svc'.
There was no endpoint listening at http://localhost:49178/Services/Issuer.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
The remote server returned an error: (404) Not Found.
HTTP GET Error
URI: http://localhost:49178/Services/Issuer.svc
The HTML document does not contain Web service discovery information.
I think the "Metadata contains a reference that cannot be resolved" line also refers to the service name resolve error.
Any ideas on what to do here? I'd appreciate any help..
Issuer.svc:
<%# ServiceHost Language="C#" Debug="true" Factory="Identity.Services.Wcf.Core.CustomSecurityTokenServiceContractFactory" Service="CustomSecurityTokenServiceConfiguration" %>
Factory:
public class CustomSecurityTokenServiceContractFactory : WSTrustServiceHostFactory
..
Service:
public class CustomSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
..
Sometimes the best way to solve this kind of problems is to create a new WCF project from scratch, configure again your endpoints etc.. and copying over your existing services from your old project, this is especially true when moving from an older version of WCF.
Here is a checklist that I follow every time I have problems with WCF services:
The Server
Make sure your service contracts are defined using interfaces with the appropriate attributes, for example:
IMyService.cs
[ServiceContract]
public interface IMyService
{
[OperationContract]
int ThisAnOperation(int a, int b);
}
Check that you have implemented your contracts using the right interface:
MyService.cs
public class MyService: IMyService
{
public int ThisAnOperation(int a, int b)
{
return a * b;
}
}
You need to have a service host to access your service, they are the files with the extension .svc:
Create a file myService.svc.
Add the following line of code, referencing the class implementing your service:
<%# ServiceHost Language="C#" Debug="true" Service="YourNamespace.MyService" CodeBehind="MyService.cs" %>
Finally, you need to set up a binding which will define which transports and protocols are available to access your server, start with a simple basic HTTP binding to check that your service is working as expected, then change it to something more production ready that includes authentication and/or encryption and compression as needed.
To setup basic HTTP binding:
Remove the block <system.serviceModel>...</system.serviceModel> from your file web.config if it's already there.
Build your solution, it should compile successfully, otherwise fix any error and try again.
Right-click your web.config file and then click on "Edit WCF Configuration", then click on "Create a New Service" and in Service type, browse and choose the DLL file generated when you compiled your service (should be in the bin folder) and select the service class you would like to publish:
Specify the contract for the service (should be automatically filled up).
In the next page select the transport protocol for your service, in this case, "HTTP", then select "Basic Web Services interoperability".
In the next page you can specify the address for the endpoint, for testing purposes, you can leave this field empty (make sure you also remove "HTTP" from the text field).
Click next, close the configuration window and save.
Now you should be able to run the service and browse to MyService.svc to access your service.
Activate metadata publishing so your service can be found, to do this, add the following behavior to your web.config:
<system.serviceModel>
<services>
<service name="WcfService1.MyService">
<endpoint binding="basicHttpBinding"
bindingConfiguration="" contract="WcfService1.IMyService"
BehaviorConfiguration="MyServiceBehaviors" />
</service>
</services>
</system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehaviors" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Now you should be able to run your project and get a metadata description page of your service within the browser, this info can be used by clients to find the service and generate a proxy of the service:
The Client
Delete any existing service references from your project.
Right click on your project name then in "Add Service Reference", input your service address and click on "Go", if everything went all right you should see your service in the Service Window:
Try to generate the proxy by finishing the wizard, rebuild your project and try it. If you still have the same problem, delete the generated reference and repeat points 1 and 2 and then:
Click on "Advanced" and uncheck "Reuse types in referenced assemblies":
Then finish the wizard and compile.
Hopefully, everything should work now!!!
I may have a similar setup as yours. In my case, I have both the STS and a service that is called by whoever wants a token. This is what you have, right?
In the Web.config for the actual STS I have:
<bindings>
<ws2007HttpBinding>
<binding name="ws2007HttpBindingConfiguration">
<security mode="TransportWithMessageCredential">
<message establishSecurityContext="false" clientCredentialType="Certificate"/>
</security>
</binding>
</ws2007HttpBinding>
</bindings>
<services>
<service name="System.ServiceModel.Security.WSTrustServiceContract" behaviorConfiguration="STSBehavior">
<endpoint address="IWSTrust13" binding="ws2007HttpBinding" bindingConfiguration="ws2007HttpBindingConfiguration" contract="System.ServiceModel.Security.IWSTrust13SyncContract" name="STSWCF"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
And in the Web.config for the service I have:
<protocolMapping>
<!-- We want to use ws2007FederationHttpBinding over HTTPS -->
<add scheme="https" binding="ws2007FederationHttpBinding" bindingConfiguration="ws2007FederationHttpBindingConfiguration"/>
</protocolMapping>
<bindings>
<ws2007FederationHttpBinding>
<binding name="ws2007FederationHttpBindingConfiguration">
<!-- We expect a bearer token sent through an HTTPS channel -->
<security mode="TransportWithMessageCredential">
<message establishSecurityContext="false">
<issuerMetadata address="https://localhost/Identity.STS.WCF/Service.svc/mex"/>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
<services>
<service name="Identity.Auth.WCF.Service" behaviorConfiguration="STSBehavior">
<endpoint address="https://localhost/Identity.Auth.WCF/Service.svc" binding="ws2007FederationHttpBinding" bindingConfiguration="ws2007FederationHttpBindingConfiguration" contract="Identity.Auth.WCF.IService" name="Identity.Auth.WCF"/>
</service>
</services>
Also, it does work for me here, even though I do get the same IntelliSense error as you, and in the very same spot.

Impersonate User in SharePoint 2010 web part to call WCF service

I have a Web Part where I am trying to call a WCF Service as the current logged in user. The Web Part work locally when debugging in Visual Studio 2013 - calling the external WCF service. I have configured Kerberos for the WCF Service as well as the SharePoint site and fee like that is all correct. I can call the WCF Service correctly from another Kerberos enabled web app fine as well as from a console app.
Now I'd like to roll this to a SharePoint farm. However after I add the solution to the farm and activate the feature on the sharepoint site...I get an error when I try to add the web part to a page. The error comes up in a box that says "The caller was not authenticated by the service.". The error comes from the actualy method call.
My web part code is as such:
WorksiteService.iWorksiteServiceClient wss = new WorksiteService.iWorksiteServiceClient("WSHttpBinding_iWorksiteService");
wss.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
wss.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
WorkSiteDocument[] wd = wss.GetDocumentsByAlias2("test");
The web.config in for the sharepoint site has this for the endpoint:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_iWorksiteService" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://myservicerd.xyz.com/WorkSiteService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_iWorksiteService" contract="WorksiteService.iWorksiteService" name="WSHttpBinding_iWorksiteService">
<identity>
<servicePrincipalName value="myservicerd.xyz.com" />
</identity>
</endpoint>
</client>
</system.serviceModel>
Any ideas on why I get that error? I'm assuming I'm not getting the current user's credentials for some reason.There is nothing in the event or sharepoint logs of the sharepoint server or wcf server. Any ideas on how I can troubleshoot this?Thank you for any assistance you can provide.
I'm not a Sharepoint Expert, but from a Kerberos perspective I would suggest to check the delegation settings in Active Directory just as Marek suggested.
In a double-hop scenario like this, the 'man' in the middle must be permitted to take on the identity of the client.
The question remains who the 'man' in the middle is, which depends on the IIS configuration.
If the IIS is configured for kernel-mode authentication the middle identity is probably the computer account if the server IIS is installed on.
Otherwise I would assume that the identity that needs delegation rights should be the identity of the application pool the web part runs in.
If you determined the identity, go to the appropriate Active Directory account (delegation tab) and select 'Account is trusted for delegation'.
Maybe this blog article can shed some light on this: http://tekaris.com/blog/2013/04/05/http-400-bad-request-kerberos-authentication-with-iis-2/

Not passing Credentials to WCF Service resulting in a 401

I'm tearing my hair out on this one, I have a WCF service that I can call through the browser and it works fine, when I call it from the web application with the below method I get a (401) Unauthorized error. And the service does not get called. What's more, when I run my web application from my local machine (debug mode using IIS Express) pointed at my dev server (IIS7) it works but when I deploy my web application to the dev server and point it to the dev server services it fails wit the 401 error. I think this is something to do with IIS7 but I'm not 100% sure and help would be super useful.
I have looked online for the answers but thus far the best I have found is this.
My service call is as follows:
var request = (HttpWebRequest) WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/json; charset=utf-8";
request.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse responce = request.GetResponse();
Stream reader = responce.GetResponseStream();
var sReader = new StreamReader(reader);
string outResult = sReader.ReadToEnd();
sReader.Close();
var result = (T) JsonConvert.DeserializeObject(outResult, typeof (T));
return result;
My configuration for the service looks like this :
<service name="RGMPServices.Householding.Services.AccountService" behaviorConfiguration="Default">
<endpoint address="" kind="webHttpEndpoint" endpointConfiguration="SecuredHttpEndpointBinding" contract="RGMPServices.Householding.Contracts.IAccountService" />
</service>
<service name="RGMPServices.Householding.Services.HouseholdService" behaviorConfiguration="Default">
<endpoint address="" kind="webHttpEndpoint" endpointConfiguration="SecuredHttpEndpointBinding" contract="RGMPServices.Householding.Contracts.IHouseholdService" />
</service>
<service name="RGMPServices.Householding.Services.UserService" behaviorConfiguration="Default">
<endpoint address="" kind="webHttpEndpoint" endpointConfiguration="SecuredHttpEndpointBinding" contract="RGMPServices.Householding.Contracts.IUserService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webBehaviour">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="SecuredHttpEndpointBinding" helpEnabled="true" automaticFormatSelectionEnabled="true">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
I have put some logging on the client service call, just before I call the service, the response is:
DEBUG 2013-10-01 13:15:13,569 452ms ServiceGetSingle - Passing Login: MYLANDOMAIN\MYLANUSERNAME
ERROR 2013-10-01 13:15:13,631 514ms ServiceGetSingle - ERROR Calling ServiceGetSingle with user credentials login: MYLANDOMAIN\MYLANUSERNAME
System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.HttpWebRequest.GetResponse()
at Householding.Common.ServiceHelper.ServiceGetSingle[T](String url)
The code looks like:
logger.Debug("Passing Login: "
+ System.Security.Principal.WindowsIdentity.GetCurrent().Name)
Even when I set the AppPool for my website to my domain account it is still not authorising me to access the WCF Service, but again: it's working for the browser. So weird!
It seems likely you're a victim of the double-hop issue when using Integrated Windows Authentication (IWA) and Kerberos. The first hop is from your browser to the web application; the second hop is from your web application to the WCF service.
Here are some resources that explain the issue more fully, and may offer a solution:
IIS, Windows Authentication and the Double Hop issue
Using Integrated Windows Authentication (IWA) in a Distributed Application Architecture
Understanding Kerberos Double Hop
You can configure Active Directory to support Kerberos delegation (usually the infrastructure guys don't like this), or you could turn off impersonation and use a "service" account for the web application and IIS app pool that can authenticate with the WCF service on behalf of the end user.
What are the default credentials on the Dev server? Try doing a log right there and see what you get.
This is what I suspect: Running locally, the credentials are YOUR windows creds. When you call the dev server from dev, the credentials would be whatever account the website is running under. If that particular account doesn't have access, then it would blow up.
How they said before, this looks like an impersonation problem.
Have you tried to start the client program with "run as" to change the credentials?
Additionally you can change this line of code
request.Credentials = CredentialCache.DefaultCredentials;
to
request.Credentials = new NetworkCredential("MyUsername", "MyPassword");
And see if it works. Also you need to create the account "MyUserName" with "MyPassword" on the web server to make it work.
These errors can be caused when the authenticated user does not have access to the physical path where the WCF service is hosted. On the dev server, open up IIS Manager and navigate to the virtual directory for the service. On the right in the Actions bar, click on "Basic Settings". Below the "Physical Path" text box, click "Connect as...". Choose "Specific User" and try setting it to a user account that you know has rights to the physical folder on the dev server. Typically, this would be a service account whose password does not expire.
When running from the browser, the browser is sending your auth credentials. Also, iis express will run as the logged in user, so this is also sending your credentials. Iis is different, it will be running as a local account. Even if you have authentication on your front end iis, that will not be passed to the backend. Windows impersonation tokens are limited in the number of hops allowed, usually 0. This is done to prevent exactly what you are doing.
If you want front end authentication to flow to the backend then you should probably do the authentication yourself and grab user/pass on the way through. Alternatively, if you do the authentication yourself you can create an impersonation token that allows a hop to another machine and it should work.

Problem authenticating with WCF service cross domain

I'm new to WCF and its security so was looking for some help on a problem I'm having.
I have a WCF service that to be deployed to every machine in a small domain. The WCF service is to be hosted in a Windows Service since it has methods in it that need to be invoked elevated. The service is very draft at the moment (it exposes meta-data - but I believe this is to be turned off later - is this possible?). It uses the net.tcp binding - The App.Config of the service is shown below:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="SvcBehavior" name="Microsoft.ServiceModel.Samples.Svc">
<endpoint address="" binding="netTcpBinding"
contract="Microsoft.ServiceModel.Samples.ISvc" />
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://*:8100/ServiceModelSamples/service" />
</baseAddresses>
<timeouts closeTimeout="00:10:00" openTimeout="00:10:00" />
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SvcBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
For a client, I have a Winforms C# application. The application serves 2 functions, it pulls static information from the service and then gives the user an option to authenticate and call the administrative methods. Therefore, the authentication is done at client level.
I am using Channelfactory to connect to the service since the hostname is variable (user is prompted for it on client start-up) and the app.config file for the client is shown below - its virtually empty:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
</bindings>
<client />
</system.serviceModel>
</configuration>
The channelfactory code is:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://Microsoft.ServiceModel.Samples", ConfigurationName = "ISvc")]
ChannelFactory<ISvc> myChannelFactory = new ChannelFactory<ISvc>(new NetTcpBinding(), "net.tcp://" + HostName + ":8100/ServiceModelSamples/service");
public static ISvc client = null;
I have an interface that descrives the methods in the service as well.
The main problem I am having is this. Say there is Machine1 and Machine2 running on domainA. Lets assume that Machine1 hosts the service and Machine2 runs the client.
When I connect to the service using a domain account domainA\User, the service works fine but say I have a local user on Machine2 and want to connect to the service as Machine2\LocalUser, I get the following error message:
The server has rejected the client credentials.
I have tried experimenting with setting the security mode to none (not something im keen on doing) but then I get an error saying the client and service have a configuration mismatch.
Is there something I can do to fix this? Also, what would happen if the service running on domainA\Machine1 was called by a user from another domain - say domainB\User2 ?
Thanks in advance - Id appreciate some insight into this!
Chada
If you turn off security on the service you must turn in off on the client as well. If you configure client in code you must set the same configuration for new instance of NetTcpBinding as you do on the service in configuration file.
When Windows security is used (default for NetTcpBinding) MachineB cannot authenticate local accounts from MachineA (there were some tricks with duplicate local users but I don't know if they work with WCF as well). That is why you have a domain. Cross domain windows authentication requires trust between domains.
If you need to authenticate cross domain users or local users you cannot use Windows authentication. There are other authentication mechanism but they require configuring certificate (at least on the service) and use either client certificate or user name and password for client authentication.

How do I connect my Silverlight app to a WCF Service?

I've been looking for this answer, and all I found was this link, but when I attempted to follow the tutorial I failed hard. What I need is to connect my Silverlight application to a database, just to show informations from a specific table. As I don't want to use the same ORM for my page and my silverlight app, I created a new WCF webservice project, and created my LINQ to SQL classes inside of it.
I tested my WCF service and it works fine, but somehow my Silverlight App doesnt reach it. I've changed the web.config file, and now it looks as follows.
My web.config
<?xml version="1.0"?> <configuration>
<connectionStrings>
<add name="bd_webportosConnectionString" connectionString="Data Source=BARNEY\DEV;Initial Catalog=bd_webportos;User ID=sa;Password=Stigeo_1_adm_1"
providerName="System.Data.SqlClient" /> </connectionStrings> <system.web>
<compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBindingConfig">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:7298/DataToSilverlight.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
contract="DataRetrieverReference.IService1" name="BasicHttpBinding_IService1" />
</client>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information
-->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> </system.serviceModel> <system.webServer>
<modules runAllManagedModulesForAllRequests="true"/> </system.webServer> </configuration>
I don't know how to solve this problem. And although I got stuck, I tried to keep going forward, but then I got stuck again in the next step, that was to add the service reference to my silverlight app. As I try to do what it says, the following message is shown:
There was an error downloading
metadata from the address. Please
verify that you have entered a valid
address.
I tested the service through WCF Test Client, and it worked, but my silverlight app doesn't reach it. I get the following exception:
An error occurred while trying to make
a request to URI
'http://localhost:7298/DataToSilverlight.svc'.
This could be due to attempting to
access a service in a cross-domain way
without a proper cross-domain policy
in place, or a policy that is
unsuitable for SOAP services. You may
need to contact the owner of the
service to publish a cross-domain
policy file and to ensure it allows
SOAP-related HTTP headers to be sent.
This error may also be caused by using
internal types in the web service
proxy without using the
InternalsVisibleToAttribute attribute.
Please see the inner exception for
more details.
Can you guys help me solving this big problem, or even showing another way to achieve what I want?
I also recently discovered that my crossdomain.xml doesn't get loaded ... but I don't know what that means.
Silverlight runs in very sandboxed environment. So when ever we want make a call to the WCF service from silverlight app, then we have to deploy simple policy.xml and crossdomain.xml in root director and application director of IIS. if you running an silverlight app from VS studio webserver and WCF is hosted in VS internal web server, then you will not experience such problem.
According to MSDN the <services> tag should be inside your <system.serviceModel> tag. Just copy the whole block in there.
Edit: About the connect to database part.
Silverlight can not magically "query" the database through the WCF service unless you create a WCF Data Service/OData. To get data from the database to your Silverlight client in a straight forward way you need to create methods in the WCF service that queries the database according to the in-parameters of the WCF method, packs it up i a suitable data structure (List<Customer> in the example in you link) and returns the result to the Silverlight client.
The error you get "There was an error downloading metadata from the address. Please verify that you have entered a valid address." is not an error relevant to the database, it is an error telling that your WCF service can not be found. That would have happened regardless if your WCF service used a database or not.
It looks like there might be further configuration errors in the WCF service, that might explain why the reference to the service can not be added. How does your dialog corresponding to "Figure 3-13. Adding a reference to the Web Service" look like? You can edit your question and insert a screen dump.
You can try this way :
http://www.dotnetspider.com/tutorials/Silverlight-Tutorial-315.aspx
Simple and easy.

Categories