I have created a web service in Visual Studio 2010 using the wsdl provided by our vendor. I have created an interface using their wsdl and implemented that interface for our implementation. They also need a SSL certificate so we have provided them certificate open ssl of windows. Web service also implements authentication using soap header.
But they are unable to connect and getting the following error
<soap:Body>
<soap:Fault>
<faultcode>soap:MustUnderstand</faultcode>
<faultstring>SOAP header Security was not understood.</faultstring>
</soap:Fault>
</soap:Body>
My web service code is as follows for your reference
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data;
using System.Data.SqlClient;
using System.Web.Services.Protocols;
using System.IO;
using Microsoft.Web.Services3;
namespace MyWebService1
{
/// <summary>
/// Summary description for PSWebService
/// </summary>
///
[WebService(Namespace = "http://tempuri.org")]
[WebServiceBinding(Name = "PSWebService", ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[SoapDocumentService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
// 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 PSWebService : Microsoft.Web.Services3.WebServicesClientProtocol, IPartStoreRequiredServiceSOAP11Binding
{
public UserCredentials consumer;
Functions objFunctions = new Functions ();
String SqlConnStr = "Data Source=test\\test;uid=sa;pwd=abc123;database=testdb";
public AeslPSWebService()
{
}
[WebMethod]
[SoapDocumentMethod(Binding = "PSWebService")]
[SoapHeader("consumer", Direction = SoapHeaderDirection.In, Required = true)]
public CustomerInformationOutput getCustomerInformation(CustomerInformationInput custLookUpInput)
{
CustomerInformationOutput cio = new CustomerInformationOutput();
try
{
if (checkUser())
{
// My business logic goes here
}
}
catch (Exception ex)
{
}
}
private bool checkUser()
{
// In this method you can check the username and password
// with your database or something
// You could also encrypt the password for more security
if (consumer != null)
{
if (consumer.Username == "sa" && consumer.Password == "abc123")
return true;
else
return false;
}
else
return false;
}
}
# region "SOAP Headers"
public class UserCredentials : System.Web.Services.Protocols.SoapHeader
{
public string Username;
public string Password;
}
# endregion
}
Please help as i am unable to resolve it.
Related
I am taking over a legacy SOAP project where I need to replace the SOAP Service with a .NET Core solution. We cannot have the SOAP client change, so we cannot look at REST, GRPC, etc. I have looked at SoapCore and CoreWCF and have both working with the SOAP header username/password auth demo, however, I'm going to use CoreWCF for the time being.
The existing SOAP service uses custom http status code responses, for example, 202 is returned after the service has been processed and in some situations, where a SOAP Fault occurs. I realize this is incorrect, however, we need to maintain the existing business logic.
My questions are:
How can I configure my service to respond with a http status code 202 after the service is completed or when a certain condition is met? IsOneWay=True OperationContract will not work as this returns immediately.
How would I configure a SOAP Fault to respond with a custom http status code?
There are many old SO posts mentioning WebOperationContext, however, I cannot seem to access this within my service. OperationContext doesn't seem to have control of the HttpStatusCode. Maybe I'm missing something.
i.e.:
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.BadRequest;
Here's my sample project breakdown:
Program.cs
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using System.Diagnostics;
namespace CoreWcf.Samples.Http
{
public class Program
{
public const int HTTP_PORT = 8088;
public const int HTTPS_PORT = 8443;
static void Main(string[] args)
{
IWebHost host = CreateWebHostBuilder(args).Build();
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options =>
{
options.ListenLocalhost(HTTP_PORT);
options.ListenLocalhost(HTTPS_PORT, listenOptions =>
{
listenOptions.UseHttps();
if (Debugger.IsAttached)
{
listenOptions.UseConnectionLogging();
}
});
})
.UseStartup<BasicHttpBindingStartup>();
}
}
Startup.cs
using CoreWCF;
using CoreWCF.Configuration;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace CoreWcf.Samples.Http
{
public class BasicHttpBindingStartup
{
public void ConfigureServices(IServiceCollection services)
{
//Enable CoreWCF Services, with metadata (WSDL) support
services.AddServiceModelServices()
.AddServiceModelMetadata();
}
public void Configure(IApplicationBuilder app)
{
var wsHttpBindingWithCredential = new BasicHttpBinding(CoreWCF.Channels.BasicHttpSecurityMode.TransportWithMessageCredential);
wsHttpBindingWithCredential.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
app.UseServiceModel(builder =>
{
// Add the Demo Service
builder.AddService<DemoService>(serviceOptions =>
{
// Set a base address for all bindings to the service, and WSDL discovery
serviceOptions.BaseAddresses.Add(new Uri($"http://localhost:{Program.HTTP_PORT}/DemoService"));
serviceOptions.BaseAddresses.Add(new Uri($"https://localhost:{Program.HTTPS_PORT}/DemoService"));
})
// Add BasicHttpBinding endpoint
.AddServiceEndpoint<DemoService, IDemo>(wsHttpBindingWithCredential, "/wsHttpUserPassword", ep => { ep.Name = "AuthenticatedDemoEP"; });
builder.ConfigureServiceHostBase<DemoService>(CustomUserNamePasswordValidator.AddToHost);
// Configure WSDL to be available over http & https
var serviceMetadataBehavior = app.ApplicationServices.GetRequiredService<CoreWCF.Description.ServiceMetadataBehavior>();
serviceMetadataBehavior.HttpGetEnabled = serviceMetadataBehavior.HttpsGetEnabled = true;
});
}
}
}
IDemo.cs (Service Interface):
using CoreWCF;
namespace CoreWcf.Samples.Http
{
// Define a service contract.
[ServiceContract]
public interface IDemo
{
//[OperationContract(IsOneWay = true)]
[OperationContract]
string DemoRequest(string tagid, string readerid, string datetime);
}
}
Demo.cs (Service):
using CoreWCF.Channels;
using Microsoft.AspNetCore.Http;
using System.Net;
namespace CoreWcf.Samples.Http
{
public class DemoService : IDemo
{
public string DemoRequest(string tagid, string readerid, string datetime)
{
return $"Received tagid: {tagid}; readerid: {readerid}; datetime: {datetime}";
}
}
}
CustomUserNamePasswordValidator.cs:
using CoreWCF;
using System.Threading.Tasks;
namespace CoreWcf.Samples.Http
{
internal class CustomUserNamePasswordValidator : CoreWCF.IdentityModel.Selectors.UserNamePasswordValidator
{
public override ValueTask ValidateAsync(string userName, string password)
{
bool valid = userName.ToLowerInvariant().EndsWith("valid")
&& password.ToLowerInvariant().EndsWith("valid");
if (!valid)
{
throw new FaultException("Unknown Username or Incorrect Password");
}
return new ValueTask();
}
public static void AddToHost(ServiceHostBase host)
{
var srvCredentials = new CoreWCF.Description.ServiceCredentials();
srvCredentials.UserNameAuthentication.UserNamePasswordValidationMode = CoreWCF.Security.UserNamePasswordValidationMode.Custom;
srvCredentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNamePasswordValidator();
host.Description.Behaviors.Add(srvCredentials);
}
}
}
Many thanks in advance for any assistance.
cheers.
OutgoingResponse StatusCode is where you set the response code, but it is not an integer value.
If you still want to use it, try ASP.NET compatibility mode. The deployment must be in IIS.
I have a problem, need to display the contents of a query in the database with webservice, serializing with Json.
My Billing List
using BiDAL.Entity.Graficos;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BiDAL.Persistence
{
public class FaturamentoIvelDAL : Conexao
{
public List<FaturamentoIvel> FindAllFaturamentoIvel()
{
try
{
OpenConnection();
Cmd = new SqlCommand("SELECT Operacao, AnoMes, TradeMarketing, SUM(ValorNF) AS ValorTotal FROM dbo.FatoFaturamentoIVEL WHERE TradeMarketing = 0 GROUP BY Operacao, AnoMes, TradeMarketing ORDER BY SUM(ValorNF) DESC", Con);
Dr = Cmd.ExecuteReader();
List<FaturamentoIvel> lista = new List<FaturamentoIvel>();
while (Dr.Read())
{
FaturamentoIvel ft = new FaturamentoIvel();
ft.Operacao = Convert.ToString(Dr["Operacao"]);
ft.AnoMes = Convert.ToString(Dr["AnoMes"]);
ft.ValorNF = Convert.ToSingle(Dr["ValorNF"]);
lista.Add(ft);
}
return lista;
}
catch (Exception ex)
{
throw new Exception("Erro ao listar Faturamento: " + ex.Message);
}
}
}
}
My WebService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
using BiDAL.Persistence;
using BiDAL.Entity;
using BiDAL.Util;
using BiFrontEnd.Controllers;
namespace BiFrontEnd
{
/// <summary>
/// Summary description for WebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[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 WebService : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(UseHttpGet= true, ResponseFormat = ResponseFormat.Json)]
public void GerarGraficoFaturamentoIvel(Conexao Con)
{
try
{
Context.Response.Clear();
Context.Response.ContentType = "application/json";
Con.OpenConnection();
Context.Response.Write(Serializer.Serializador(FindAllFaturamentoIvel));
}
catch (Exception)
{
throw;
}
}
}
}
In the code line "Context.Response.Write(Serializer.Serializador(FindAllFaturamentoIvel));" is giving error in FindAllFaturamentoIvel
I have a long-running WCF service hosted in a Windows service. I have a service library whose purpose is to report on the state of the service. How can I get to the instance of the service from inside an instance of the service library?
To illustrate, I created a service that records the time it started, and exposes a method to report how long it's been running. The service library needs to be able to call the service's ElapsedSeconds() method, so the the library needs a reference to the running service.
I thought I could use OperationContext.Current. Here's my service library class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace TimerService
{
public class TimerServiceLib : ITimerServiceLib
{
TheTimerService m_timerService;
public TimerServiceLib()
{
var currentContext = OperationContext.Current;
var instanceContext = currentContext.InstanceContext;
m_timerService = (TheTimerService)instanceContext.GetServiceInstance();
}
public double SecondsSinceStart()
{
return m_timerService.ElapsedSeconds();
}
}
}
But the call to GetServiceInstance() creates a new instance of TimerServiceLib(), which of course gives me an infinite loop. So, what is the correct way to do this?
Here is my service class, actually being hosted in a console application:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace TimerService
{
public partial class TheTimerService : ServiceBase
{
private DateTime m_startTime;
ServiceHost m_svcHost;
public TheTimerService()
{
InitializeComponent();
Init();
m_startTime = DateTime.Now;
}
public double ElapsedSeconds()
{
return (DateTime.Now - m_startTime).TotalSeconds;
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
public void Init()
{
if (m_svcHost != null)
{
m_svcHost.Close();
}
string httpAddress = "http://localhost:1234/TimerService";
string tcpAddress = "net.tcp://localhost:1235/TimerService";
Uri[] adrbase = { new Uri(httpAddress), new Uri(tcpAddress) };
m_svcHost = new ServiceHost(typeof(TimerServiceLib), adrbase);
ServiceMetadataBehavior mBehave = new ServiceMetadataBehavior();
m_svcHost.Description.Behaviors.Add(mBehave);
var debugBehavior = m_svcHost.Description.Behaviors.Find<ServiceDebugBehavior>();
debugBehavior.IncludeExceptionDetailInFaults = true;
BasicHttpBinding httpBinding = new BasicHttpBinding();
m_svcHost.AddServiceEndpoint(typeof(ITimerServiceLib), httpBinding, httpAddress);
m_svcHost.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
NetTcpBinding tcpBinding = new NetTcpBinding();
m_svcHost.AddServiceEndpoint(typeof(ITimerServiceLib), tcpBinding, tcpAddress);
m_svcHost.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
m_svcHost.Open();
// SimShopServiceLib.m_shop = new CSimShopManager();
}
}
}
You can do it this way:
First, modify your TimerServiceLib and do the constructor injection of TheTimerService:
public class TimerServiceLib : ITimerServiceLib
{
private readonly TheTimerService m_timerService;
public TimerServiceLib(TheTimerService theTimerService)
{
m_timerService = theTimerService;
}
public double SecondsSinceStart()
{
return m_timerService.ElapsedSeconds();
}
}
Then, in your Init() upon creation of ServiceHost, instantiate first your service and pass the TheTimerService. Since your are creating the ServiceHost inside your windows service, wich is TheTimerService you can pass this.
Uri[] adrbase = { new Uri(httpAddress), new Uri(tcpAddress) };
var timerServiceLib = new TimerServiceLib(this)
m_svcHost = new ServiceHost(timerServiceLib , adrbase);
For more details about passing object in you service see this link.
Disclaimer : The above code is not tested.
I've been working on a small MVC-project which since I converted to more of an MVC-approach has stopped working.
The program consuming the web-service is a simple console-application with its own controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ConsoleApplication.ServiceReference1;
namespace ConsoleApplication
{
class ConsoleController
{
ServiceReference1.WebService2SoapClient webservice = new ServiceReference1.WebService2SoapClient();
public List<Employee> GetEmployees()
{
return webservice.GetEmployees().ToList();
}
}
}
The web-service consists of a Employee-class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace webservice
{
public class Employee
{
public string _socialSN { get; set; }
public string _lastName { get; set; }
public string _firstName { get; set; }
public Employee(string socialSN, string firstName, string lastName)
{
this._firstName = firstName;
this._lastName = lastName;
this._socialSN = socialSN;
}
}
}
A data access layer:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
namespace webservice
{
public class DAL
{
private SqlConnection con;
private SqlCommand cmd;
public void GetConnection()
{
con = new SqlConnection("Data Source=****;Initial Catalog=DB2015;Persist Security Info=True;User ID=****;Password=***********");
}
public List<Employee> GetEmployees()
{
GetConnection();
con.Open();
cmd = con.CreateCommand();
cmd.CommandText = "SELECT SocialSN, Name, Surname FROM Employee";
SqlDataReader reader = cmd.ExecuteReader();
List<Employee> employeeList = new List<Employee>();
if (reader.HasRows)
{
while (reader.Read())
{
employeeList.Add(new Employee(reader.GetString(0), reader.GetString(1), reader.GetString(2)));
}
}
else
{
employeeList = null;
}
reader.Close();
con.Close();
reader.Dispose();
con.Dispose();
return employeeList;
}
}
}
A BackController:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace webservice
{
class BackController
{
DAL dal = new DAL();
public List<Employee> GetEmployees()
{
return dal.GetEmployees();
}
}
}
And finally the webservice-code itself:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data;
using System.Data.SqlClient;
namespace webservice
{
/// <summary>
/// Summary description for WebService2
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[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 WebService2 : System.Web.Services.WebService
{
BackController bcontroller = new BackController();
[WebMethod]
public List<Employee> GetEmployees()
{
return bcontroller.GetEmployees();
}
}
}
Whenever I try to add a new service-reference to my console-application I get this error:
Error part 1 http://i.imgur.com/UVw1cAO.png
Error part 2 http://i.imgur.com/N0dF159.png
I cannot figure out what is wrong. It worked fine before I changed to MVC. I've tried to clean the projects, rebuild them and create them all from scratch again and just simply won't work.
Please let me know if you've got any ideas what could be wrong or if you need additional information.
Thanks!
It sounds like you've upgraded some components but the code is still trying to latch onto the old version. Essentially something in your code is looking for say version 1.1.0.1 and you've got version 2.1.0.1. or something like that. You'll need to either redirect to the correct assembly in your web config or find another way to get your application to accept the newer version.
Here are some links you can check out for some tips but these can be elusive bugs to sort out.
From stackoverflow:
The located assembly's manifest definition does not match the assembly reference.
that link has this one inside it:
http://blogs.msdn.com/b/junfeng/archive/2004/03/25/95826.aspx
And here is an independent blogger's take on it:
http://www.codingdefined.com/2014/10/error-located-assemblys-manifest.html
I'm newbie to webservices..
I have a Silverlight 4 application, with a login page created be me.
I have created a webservice:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Security;
namespace MagNET.Web.WebServices
{
/// <summary>
/// Summary description for AuthenticationService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[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 AuthenticationService : System.Web.Services.WebService
{
[WebMethod(EnableSession = true)]
public bool AuthenticateUser(string username, string password)
{
//bool valid = Membership.ValidateUser(username, password);
bool valid = true;
if (valid)
{
FormsAuthentication.SetAuthCookie(username, false);
Session["username"] = username;
}
else
{
Session["username"] = null;
}
return valid;
}
[WebMethod(EnableSession = true)]
public string HelloWorld()
{
if (!IsLoggedIn())
{
throw new Exception("User is not logged in!!!");
}
else
{
return "Hello World!";
}
}
private bool IsLoggedIn()
{
if (Session["username"] != null)
return true;
else
return false;
}
}
}
I use this code to find out if user is logged in:
MagNET.AuthenticationService.AuthenticationServiceSoapClient svc =
new MagNET.AuthenticationService.AuthenticationServiceSoapClient();
svc.HelloWorldCompleted += new EventHandler<AuthenticationService.HelloWorldCompletedEventArgs>(svc_HelloWorldCompleted);
svc.HelloWorldAsync();
void svc_HelloWorldCompleted(object sender, AuthenticationService.HelloWorldCompletedEventArgs e)
{
MessageBox.Show("User logged in");
}
I don't know how to invoke the AuthenticateUser method of the web service (I don't know how to effectively log in a user when login button from my login page is pressed).
Just use AuthenticateUser method instead HelloWorld method:
MagNET.AuthenticationService.AuthenticationServiceSoapClient svc =
new MagNET.AuthenticationService.AuthenticationServiceSoapClient();
svc.AuthenticateUserCompleted += new EventHandler<AuthenticationService.AuthenticateUserCompletedEventArgs>(svc_AuthenticateUserCompleted);
string username = txtBoxUsername.Text;
string password = txtBoxPassword.Password;
svc.AuthenticateUserAsync(username, password);