Dinâmica C # .NET Webservice
-
06-09-2019 - |
Pergunta
Eu estou usando uma classe em um projeto C # ASP.NET para permitir que um script escrito em alguma linguagem de script aleatória para expor métodos webservice dinamicamente - em outras palavras, o script deve ser capaz de expor um método de qualquer nome com qualquer assinatura (contanto que ele é válido, pelo menos) para o mundo exterior através desta interface SOAP (capaz de adicionar e remover-los à vontade, sem a necessidade de uma alteração de código rígido), e como tal necessidade I para ser capaz de criar uma classe webservice em C # ao ser capaz de adicionar e dinamicamente métodos remover pelo tempo de execução.
Agora, o melhor plano que eu tenho sido capaz de chegar a até agora é (runtime) gerar código C # para representar o webservice, usando System.Reflection.Emit para compilá-lo e, em seguida, carregar o assembly em tempo de execução - tudo sempre o script adiciona ou remove um método de / para o serviço (não deve acontecer muitas vezes, mente).
Alguém tem uma idéia melhor do que isso?
Solução
Você pode modificar WSDL usando SoapExtensionReflector classe. De Kirk Evans Blog :
O SoapExtensionReflector é chamado quando o seu tipo está sendo refletido sobre para fornecer a definição WSDL para o seu serviço. Você pode aproveitar este tipo de interceptar a chamada reflexão e modificar a saída WSDL.
O exemplo a seguir remove o primeiro método de métodos de serviço 2 web:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public int Multiply(int a, int b)
{
return a * b;
}
}
Crie uma classe herdada de SoapExtensionReflector:
namespace TestWebservice
{
public class MyReflector : SoapExtensionReflector
{
public override void ReflectMethod()
{
//no-op
}
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
if (description.PortTypes[0].Operations.Count == 2)
description.PortTypes[0].Operations.RemoveAt(0);
if (description.Messages.Count == 4)
{
description.Messages.RemoveAt(0);
description.Messages.RemoveAt(0);
}
foreach (Binding binding in description.Bindings)
{
if (binding.Operations.Count == 2)
binding.Operations.RemoveAt(0);
}
if (description.Types.Schemas[0].Items.Count == 4)
{
description.Types.Schemas[0].Items.RemoveAt(0);
description.Types.Schemas[0].Items.RemoveAt(0);
}
}
}
}
Adicione isto a seção de configuração / system.web no web.config:
<webServices>
<soapExtensionReflectorTypes>
<add type="TestWebservice.MyReflector, TestWebservice" />
</soapExtensionReflectorTypes>
</webServices>
Isso deve dar-lhe um ponto de partida para remover dinamicamente os métodos de documento WSDL. Você também precisa jogar NotImplementedException de método web se ele estiver desativado.
Finalmente, você precisa desativar a documentação de serviço web produzido invocando .asmx endpoint sem? WSDL parâmetro. Set atributo href do elemento wsdlHelpGenerator a algum URL. Você pode usar DefaultWsdlHelpGenerator.aspx como um ponto de partida para o seu próprio manipulador de documentação. Veja a pergunta na documentação do serviço web em arquivos XML, agosto de 2002 .
Outras dicas
XMLRPC é bastante morto, não é?
SABÃO implica uma WSDL. Como você gerar o WSDL dinamicamente?
Você deve olhar para usar WCF. Eu espero que você vai ser capaz de assumir o controle do processo de gerar o WSDL (e outros metadados), mas você também deve ser capaz de assumir o controle do processamento de mensagens recebidas. Em particular, você será capaz de examinar as mensagens recebidas para determinar qual script para ser executado, o que parâmetros para passar, etc.
Você pode criar um serviço WCF com um tipo de entrada e saída de xs:any
e lidar com a solicitação de entrada como um Message
cru. Isso permitiria que você a aceitar qualquer tipo de dados e retornar qualquer tipo de dados. Você não iria usar contratos de dados ou tipos estáticos, apenas um Message
e um Message
fora.
O problema com esta abordagem é que a geração de um proxy a partir do WSDL realmente não faz nada para ajudar o consumidor que não fornecem um wrapper para chamar o método. Fornecendo dados que seja aceitável para o método exigiria tipos de dados de enrolar, etc, que não é tão difícil, é só não tão intuitivo como um contrato duro, digitado.
Tem que ser uma interface SOAP? Isso soa como ele poderia ser mais adequado para uma rota / REST / etc API baseada. Você poderia fazer algo em ASP.NET MVC (com um método IController.Execute
personalizada que resolve a ação para o método) muito facilmente (na verdade, eu estou trabalhando em algo muito similar para alguns dos meus próprios código no momento).
Por exemplo, você pode ter rotas:
http://myserver/myservice/mymethod
que aceita (seja no corpo ou args) a carga útil (parâmetros), e retorna o resultado na resposta. Em não-MVC você deve ser capaz de fazer algo semelhante com um manipulador genérico mapeados-curinga.
Aqui está uma sugestão:
- Use WCF.
-
Criar um WSDL do WCF usando informações no seguinte blogue post:
http: //www.pluralsight .com / comunidade / blogs / kirillg / Arquivo / 2006/06/18 / 28380.aspx
-
Você pode então publicar estas informações usando MEX.
-
Os serviços são, em seguida, aberto para o seu clientes a carga para baixo os dados de meta e chamar os serviços.