I'm trying to create a small Windows Forms Application that uses data from a SharePoint List.
I've created a Service Reference which gave me all the SOAP-methods I need. It looks similar as to when I insert the WSDL in SoapUI, so I'm assuming the reference is correct as it is.
Afterwards I created a class in my DAL that you can view below:
public class Studies
{
//Constants
private const string _StudyListGuid = "{DA154DB9-1BE8-4C80-B94E-7EE4B8109905}";
private const string _StudyViewGuid = "{909C4BED-FB5F-49E5-ABE9-375BA15BBBFF}";
public List<Study> GetStudies()
{
var studyRequest = CreateRequest(); // <-- Fills in the constants in a GetListItemsRequest variable
var soap = new ListsSoapClient();
if (soap.ClientCredentials != null)
{
//soap.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
//soap.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
soap.ClientCredentials.Windows.ClientCredential.UserName = "username";
soap.ClientCredentials.Windows.ClientCredential.Password = "pwd";
}
//ERROR HAPPENS ON THIS LINE
var studyResponse = soap.GetListItems(studyRequest.Body.listName, studyRequest.Body.viewName, studyRequest.Body.query,studyRequest.Body.viewFields,studyRequest.Body.rowLimit, studyRequest.Body.queryOptions, studyRequest.Body.webID);
MessageBox.Show(studyResponse.ToString());
return TranslateResponse(studyResponse); //<-- Not yet implemented
}
}
And here's my App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ListsSoap">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm"/>
</security>
</binding>
<binding name="ListsSoap1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://website.com/_vti_bin/Lists.asmx"
binding="basicHttpBinding" bindingConfiguration="ListsSoap"
contract="SharepointService.ListsSoap" name="ListsSoap" />
</client>
</system.serviceModel>
</configuration>
Now, for the actual issue. Whenever I run my application and I call the GetStudies() method I get an error saying:
An unhandled exception of type 'System.ServiceModel.Security.MessageSecurityException' occurred in mscorlib.dll
Additional information: The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM'.
With an InnerException that says:
The remote server returned an error: (401) Unauthorized.
Now that all that has been said, I think the problem is that the request I'm sending out isn't authorized (duh). But I thought it would be.. (see code from Studies.cs).
So my first question is: Do I still need to authorize for the request, and if so, how do I do that?
If not, how would I be able to get the ListItems that I want?
I'm sorry for the long post but this is my first time using C# to get SharePoint data and I have no idea what data is actually important and what isn't so I just posted everything (I think). So if anyone has some feedback as to what information is obsolete and which necessary, I'm happy to edit the post.
Kind regards
Gravinco
Related
I was given a configuration of SOAP service, the configuration contained user name (in domain\username format), service address and password. I used Visual Studio, option Add -> Service Reference to add the service to my project. I have the following auto-generated configuration in the App.config file.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="DdpBinding" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://server_name:8080/Gordic/Ginis/Ws/test/HULT/DDP01/Ddp.svc"
binding="basicHttpBinding" bindingConfiguration="DdpBinding"
contract="GINIS_DDP_Test.DdpPortType" name="DdpPort" />
</client>
</system.serviceModel>
</configuration>
I added the following call to test the service.
class Program
{
static void Main(string[] args)
{
string username = "DOMAIN\\username";
string password = "password";
WakeupRequest requestXml = new WakeupRequest();
using (var client = new DdpPortTypeClient())
{
client.ClientCredentials.UserName.UserName = username;
client.ClientCredentials.UserName.Password = password;
client.Wakeup();
}
}
}
However, the last line throws the following error.
System.ServiceModel.FaultException: 'An error occurred when verifying security for the message.'
The developer of the software declares to implement the WS-Security standard, but I have no more information.
What should I update to make the system work?
So i have the below data in app.config of the project that has a serrvice reference:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="P4U" />
<binding name="P4U1">
<security mode="TransportWithMessageCredential" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://*.svc"
binding="basicHttpBinding" bindingConfiguration="P4U" contract=*.ServiceContract"
name="P4U" />
<endpoint address="https://*.svc"
binding="basicHttpBinding" bindingConfiguration="P4U1" contract="*.ServiceContract"
name="P4U1" />
</client>
</system.serviceModel>
I cant use this data in config. Instead, i have to create them in code. I used BasicHttpBinding and it works fine for http calls but i can get it to work for https. I tried basichttps and wshttpbinding. The username and password is send in header. Any idea what to do?
I tried with TransportWithMessageCredential with basichttp and basichttps.
Below detail is from the client document:
For each request a SOAP header is required, like in the sample:
…
<soap:Header>
<Authentication xmlns="http://*">
<User>customer specific, to be provided</User>
<Password>customer specific, to be provided</Password>
</Authentication>
</soap:Header>
Below code is that i have right now. It is the constructor:
private Binding serviceBinding ;
public ShippingService(string url, AuthenticationHeader webAuthenticationHeader, LogHelper logger)
{
authenticationHeader = webAuthenticationHeader;
this.Logger = logger;
var uri = new Uri(url);
if(uri.Scheme== "https")
{
this.serviceBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
}
else
{
this.serviceBinding = new BasicHttpBinding();
}
this.endpointAddress = new EndpointAddress(url);
}
And in the service call method i have the below line:
ServiceContractClient clientService = new ServiceContractClient (serviceBinding, endpointAddress);
The first exception i got was one below when i was using wshttpbinding:
Content Type application/soap+xml; charset=utf-8 was not supported by service https://*ervice.svc. The client and service bindings may be mismatched. For HTTP's.
I changed back to basic and since then i have been only getting the below exception:
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
If you end up with getting an exception that doesn’t give a lot of clue on what is the root cause( like the fault state we were getting), do the below steps to guide you find possible solution
Update the web.config to generate service logs
https://learn.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/configuring-message-logging
Run the application so you hit the error
Open the service log to find the root cause
[ServiceLogError]https://imgur.com/a/3wPgo
I got the error: Username is not provided. Even though while debugging, the exception i got was service is in faulted state.
Use the power of google:
https://amadotech.blogspot.in/2009/11/error-username-is-not-provided-specify.html
So in short i had to add the below two lines of code
clientService.ClientCredentials.UserName.UserName = "xyz";
clientService.ClientCredentials.UserName.Password = "123";
Rest of the code remains same
i just had a problem adding webservice that its solved in this thread
error on adding webservice
now i just have a problem by calling its method
this is my app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="sedardIPSoap" />
</basicHttpBinding>
<customBinding>
<binding name="sedardIPSoap12">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://service.proapp.ir/service/sedardIP.asmx"
binding="basicHttpBinding" bindingConfiguration="sedardIPSoap"
contract="sedardip_set.sedardIPSoap" name="sedardIPSoap" />
<endpoint address="http://service.proapp.ir/service/sedardIP.asmx"
binding="customBinding" bindingConfiguration="sedardIPSoap12"
contract="sedardip_set.sedardIPSoap" name="sedardIPSoap12" />
</client>
</system.serviceModel>
so when i try calling my function like this
sedardip_set.sedardIPSoapClient nm = new sedardip_set.sedardIPSoapClient();
nm.set_ip("x1", "x2", "x3");
it throws this exception
An endpoint configuration section for contract 'sedardip_set.sedardIPSoap'
could not be loaded because more than one endpoint configuration for that
contract was found. Please indicate the preferred endpoint configuration
section by name.
so i tried deleting one of the endpoints from app.config, after that it throws this exception
There was no endpoint listening at http://service.proapp.ir/service/sedardIP.asmx
that could accept the message. This is often caused by an incorrect address or
SOAP action. See InnerException, if present, for more details.
inner exception
{"The remote server returned an error: (404) Not Found."}
i just run service on my visual studio (locally) and by deleting second endpoint its just worked !
so can anyone plz help me to get this working on http://service.proapp.ir/service/sedardIP.asmx plz??
Is there a reason you need to use a web reference? A service reference is the updated, newer way of doing things, but if you need to use the web reference for some reason then that's fine too.
If you go the service reference route you can specifically name the endpoint you wish to use, for example:
sedardip_set.sedardIPSoapClient nm = new sedardip_set.sedardIPSoapClient("sedardIPSoap12");
nm.set_ip("x1", "x2", "x3");
It may have a new name after setting up the service reference but you would just substitute the new name in place of the sedardIPSoap12.
I'm new to Service Reference stuff so I might need simple explanation.
I got a WSDL:
https://test.servicebench.com/servicebenchv5/services/CRMServiceOrderService?wsdl
I added the Service Reference in my project via MVS2013 without any problem.
Here's the autogenerated app.config file :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CRMServiceOrderBinding">
<textMessageEncoding messageVersion="Soap11" />
<httpsTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint
address="https://test.servicebench.com/servicebenchv5/services/CRMServiceOrderService"
binding="customBinding"
bindingConfiguration="CRMServiceOrderBinding"
contract="ServiceBenchReference.CRMServiceOrderPortType"
name="CRMServiceOrderPort" />
</client>
</system.serviceModel>
</configuration>
Now, every requests I try to make to the server replies me : "Unauthorized".
I pretty sure it's because I didn't passed the required credentials in the SOAP request header.
I need to pass it 3 credentials (or info?) : ServiceBenchID, UserID and password.
I've tried using :
CRMServiceOrderPortTypeClient ServiceOrder = new CRMServiceOrderPortTypeClient();
ServiceOrder.ClientCredentials.UserName.UserName = myUserID;
ServiceOrder.ClientCredentials.UserName.password = myPassword;
but it didn't work. I checked the request via Fiddler and I didn't saw the credentials passed in the header.
So here's my question : How can I get these 3 custom credentials information to be passed in the header correctly ? (So I get a response from the server)
After searching a couple more hours, I manage to find a suitable solution !
Thanks to Thorarin for the piece of code,
How can I pass a username/password in the header to a SOAP WCF Service
It seems that having custom bindings in the app.config file is forcing you to add the security elements manually. I don't think its the best way to do it, but its working like this.
I found this question, but it seems like not my way:(
I have client service (console app), and at server side- Bitrix CMS web-service.
So, all works well , but when i update service someday on my VS 2012 and
call Send(...) method- i got error:
Received from the server authentication header "NTLM". HTTP request is not allowed for client authentication scheme "Ntlm". Received from the server authentication header "NTLM".
(it is google translate)
I try to delete and recreate service, restart VS, restart Windows- it is not working.
So, app.config :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="CTfsTasksWSBinding">
<security mode ="TransportCredentialOnly">
<transport clientCredentialType="Ntlm"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://server.domen.local/tfs_tasks_ws.php"
binding="basicHttpBinding" bindingConfiguration="CTfsTasksWSBinding"
contract="Bitrix.CTfsTasksWSInterface" name="CTfsTasksWSSoap" />
</client>
</system.serviceModel>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source = |SQL/CE|" />
</connectionStrings>
</configuration>
So, my code:
Bitrix.CTfsTasksWSInterfaceClient cll = new Bitrix.CTfsTasksWSInterfaceClient();
cll.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(loginn, passwd);
cll.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
I create new simple console app and paste some code from main app- i have the same error.
Please help me to fix this problem.
Thank you.
I have not valid password.
All works.