Upload file to Sharepoint from External MVC Web Application - c#

How can I use Sharepoint's default CopyIntoItems method to upload a new file into sharepoint from an external web application by passing in a sharepoint username and password. I don't want to use the default credentials because I'm using SQL server based forms authentication on the MVC web application.
I've tried the following:
Where CopySoapClient is the webservice connected to this url.
http://sharepointaddress/_vti_bin/copy.asmx
Code Sample
public static bool UploadSharePointFile(string file, string destination)
{
bool success = false;
CopySoapClient client = new CopySoapClient();
client.ClientCredentials.Windows.ClientCredential = new NetworkCredential("username", "password", "domain");
try
{
client.Open();
string filename = Path.GetFileName(file);
string destinationUrl = destination + filename;
string[] destinationUrls = { destinationUrl };
FieldInformation i1 = new FieldInformation { DisplayName = "Title", InternalName = "Title", Type = FieldType.Text, Value = filename };
FieldInformation[] info = { i1 };
CopyResult[] result;
byte[] data = File.ReadAllBytes(file);
uint ret = client.CopyIntoItems(filename, destinationUrls, info, data, out result);
if (result != null && result.Length > 0 && result[0].ErrorCode == 0)
success = true;
}
finally
{
if (client.State == System.ServiceModel.CommunicationState.Faulted)
client.Abort();
if (client.State != System.ServiceModel.CommunicationState.Closed)
client.Close();
}
return success;
}
The problem is that I keep getting the following error:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'.
When I tried putting this in the web.config in the web service bindings:
<security mode="Transport">
<transport clientCredentialType="Ntlm" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
Then I got the following error:
The provided URI scheme 'http' is invalid; expected 'https'. Parameter name: via

I figured it out. All I need to do was change the security mode in the web.config to
TransportCredentialOnly
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>

Related

InnerChannel = 'webServiceProxy.InnerChannel' threw an exception

I am trying to Consume WCF Service for SSRS Reports.
I have tried to exceed the message size limit to But it gives me with the exceptions which is as follows :
InnerChannel = 'webServiceProxy.InnerChannel' threw an exception of type 'System.ServiceModel.CommunicationObjectFaultedException'
Channel = 'webServiceProxy.Channel' threw an exception of type 'System.ServiceModel.CommunicationObjectFaultedException'
Code to Export on Server Side to Consume WCF..
try
{
var webServiceProxy = new ReportExecutionServiceSoapClient(wcfEndpointConfigName);
// End Point Name is Coming here which is written in web Config file : basicHttpEndpoint
webServiceProxy.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
webServiceProxy.ClientCredentials.Windows.ClientCredential = clientCredentials;
// Init Report to execute
ServerInfoHeader serverInfoHeader;
ExecutionInfo executionInfo;
ExecutionHeader executionHeader = webServiceProxy.LoadReport(null, report, null,
out serverInfoHeader, out executionInfo);
// Attach Report Parameters
webServiceProxy.SetExecutionParameters(executionHeader, null, parameters, null, out executionInfo);
// Render
serverInfoHeader =
webServiceProxy.Render(executionHeader, null, GetExportFormatString(format), null,
out output, out extension, out mimeType, out encoding, out warnings,
out streamIds);
}
catch (FaultException e)
{
throw new FaultException(e.Message);
}
Web Config File
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ReportExecutionServiceSoap" receiveTimeout="05:00:00"
sendTimeout="05:00:00" allowCookies="true" maxReceivedMessageSize="5242880">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://../ReportServer/ReportExecution2005.asmx"
binding="basicHttpBinding" bindingConfiguration="ReportExecutionServiceSoap"
contract="MyServiceReference.ReportExecutionServiceSoap" name="basicHttpEndpoint" />
</client>
</system.serviceModel>
Can some onw guide me where I am doing wrong I been stuck into this for days.

Why web services call only succeeds when pre logined through browser atleast once a day on server

I have following bindings on server side,
<bindings>
<basicHttpBinding>
<binding name="my_BasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
and client code running in console on same server,
System.Net.NetworkCredential creds = new NetworkCredential("UserName ", "password", "domain");
var binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; //.Ntlm; // Basic;
EndpointAddress endpoint = new EndpointAddress("https://example.portal.com + "/_vti_bin/MyServiceFolder/MyService.svc");
ChannelFactory<MyType> factory = new ChannelFactory<MyType>(binding, endpoint);
factory.Credentials.Windows.ClientCredential = creds;
factory.Credentials.UserName.UserName = creds.UserName;
factory.Credentials.UserName.Password = creds.Password;
//factory.Credentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
//factory.Credentials.Windows.AllowNtlm = true;
MyType proxy = factory.CreateChannel();
string result = proxy.MyMethod();
Now it usually throws 401 but when I login through browser using same username to view .svc file and try this code again... IT WORKS. BUT again next morning it won't work till I repeat the steps.
Some more details can be found here but with different settings and scenario -
How to make these web services work, man in middle is KEMP too
Could it be related to SharePoint or authentication protocols or the way Kerborse works etc.. got no clue ?

WCF Consumer not attaching client credentials to header

I have a WCF service that uses username authentication, I have a console app that consumes the service and attempts to access a protected method. I run the code and Fiddler says in the auth tab:
No Proxy-Authorization Header is present.
No Authorization Header is present.
Here is my accessing code:
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic;
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Default;
binding.Security.Transport.Realm = "MyRealm";
ServiceReference1.MobileAPIClient serviceProxy = new ServiceReference1.MobileAPIClient(binding, new EndpointAddress("https://xx.xx.xx.xx/InventoryServices.MobileApi.svc"));
serviceProxy.ClientCredentials.UserName.UserName = "test";
serviceProxy.ClientCredentials.UserName.Password = "test123";
serviceProxy.ChannelFactory.Credentials.UserName.UserName = "test";
serviceProxy.ChannelFactory.Credentials.UserName.Password = "test123";
try
{
serviceProxy.Test();
}
catch (Exception ex)
{
var ex2 = ex;
}
Why are the credentials not being attached to the header?
There is handshaking mode in wcf. So client and service exchange with credentials before first request and then they use only session token.
To disable this mode you should set in web.config
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" negotiateServiceCredential="false" establishSecurityContext="false"/>
</security>

How to set proxy credentials to specific wcf client?

I need to connect to some public wcf service, but there is some proxy between me and service.
If i use default proxy settings such as
<system.net>
<defaultProxy useDefaultCredentials="true" />
</system.net>
or
HttpWebRequest.DefaultWebProxy
it works perfectly fine
but i don't need to set proxy settings for entire application, i need to set it for specific connection. So how I can do that?
I saw ProxyAddress property
(client.Endpoint.Binding as BasicHttpBinding).ProxyAddress
but there is no any properties for credentials...
I was thinking to somehow modify HttpWebRequest, but I do not know how to get it...
Solved
Thank you all for your answers.
Answer of AntonK suitable for solving my problem.
At the time when this question was actual, I solved it in the same way, but without the use of web.config and wrote this method
void SetProxySettings<TChannel>(ClientBase<TChannel> client,
bool useProxy, string address, int port, string login, string password)
where TChannel : class
{
if (!useProxy) return;
var b = client.Endpoint.Binding as BasicHttpBinding;
if (b == null)
{
System.Diagnostics.Debug.WriteLine("Binding of this endpoint is not BasicHttpBinding");
return;
}
b.ProxyAddress = new Uri(string.Format("http://{0}:{1}", address, port));
b.UseDefaultWebProxy = false; // !!!
b.Security.Mode = BasicHttpSecurityMode.Transport;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; // !!!
b.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic; // !!!
if (client.ClientCredentials == null) return;
client.ClientCredentials.UserName.UserName = login;
client.ClientCredentials.UserName.Password = password;
}
Here's an article dealing with this issue.
http://blogs.msdn.com/b/stcheng/archive/2008/12/03/wcf-how-to-supply-dedicated-credentials-for-webproxy-authentication.aspx
In summary, this is how to set a proxy for a specific service in the web.config. In the binding config, set proxyAddress="http://myproxy:8080" and set useDefaultWebProxy="false"
<bindings>
<basicHttpBinding>
<binding name="SubscriberFulfilmentServiceSOAP12Binding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:01:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="false"
proxyAddress="http://myproxy:8080"
messageEncoding="Text">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647"
maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
I found a solution. You have to update WCF to the latest.
Go to NuGet Package Manager -> Update all related Project URL of WCF There must be:
System.ServiceModel.Security
System.ServiceModel.NetTcp
System.ServiceModel.Http
This apply to .net core 2.1 version.
You can try this
HttpWebRequest request = HttpWebRequest.Create("URI") as HttpWebRequest;
var proxy = new WebProxy(HttpWebRequest.GetSystemWebProxy().GetProxy(request.RequestUri), true);
proxy.Credentials = new NetworkCredential(proxyUserName, proxyPassword, DomainName);
request.Proxy = proxy;
hope it helps

Problem with authentication on java ws

I have application in C# that consume Java WS. Everything worked fine until WS was configured to use authentication. Now I should user login i password to execute methods from WS but I'm not sure how to do it.
I've try
var client = new MyBeanClient();
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "";
client.addConsumer("whatever", "", "", "");
But I get
SecurityMessageException-{"The HTTP request is unauthorized with client
authentication scheme 'Anonymous'. The authentication header received from
the server was 'Negotiate,NTLM'."}
InnerException - (WebException) - {"The remote server returned an error:
(401) Unauthorized."}.
What's wrong?
Thanks
Try this:
var credentialCache = new CredentialCache();
var credentials = new NetworkCredential("username", "password", "domain");
credentialCache.Add(new Uri(client.Url), "NTLM", credentials);
client.Credentials = credentialCache;
client.addConsumer("whatever", "", "", "");
UPDATE:
Sorry in my first post I thought you were using wsdl.exe to generate the client proxy. For a WCF client you need to configure the endpoint:
var basicHttpBinding = new BasicHttpBinding();
basicHttpBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
basicHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
var endpoint = new EndpointAddress("http://example.com/myWindowsAuthN");
var client = new MyBeanClient(basicHttpBinding, endpoint);
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
client.ChannelFactory.Credentials.Windows.ClientCredential.Domain = "domain";
client.ChannelFactory.Credentials.Windows.ClientCredential.UserName = "username";
client.ChannelFactory.Credentials.Windows.ClientCredential.Password = "password";
UPDATE2:
I've used the following configuration to invoke web services protected with NTLM authentication. In app.config of the client put the following:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="NtlmBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="http://example.com/SomeWindowsAuthenticatedService"
binding="basicHttpBinding"
bindingConfiguration="NtlmBinding"
contract="IOperationContractOfTheService"
name="WSTestSoap" />
</client>
</system.serviceModel>
and then you could set the corresponding credentials before invoking the method:
using (var client = new MyBeanClient())
{
client.ChannelFactory.Credentials.Windows.ClientCredential =
new NetworkCredential("username", "password", "DOMAIN");
client.addConsumer("whatever", "", "", "");
}

Categories

Resources