동적 C#.NET 웹 서비스
-
06-09-2019 - |
문제
임의의 스크립팅 언어로 작성된 스크립트가 웹 서비스 메서드를 동적으로 노출할 수 있도록 C# ASP.NET 프로젝트에서 클래스를 사용하고 있습니다. 즉, 스크립트는 서명이 있는 모든 이름의 메서드를 노출할 수 있어야 합니다. 어쨌든 유효하기 때문에) 이 SOAP 인터페이스를 통해 외부 세계에 연결됩니다(하드 코드 변경 없이 마음대로 추가 및 제거 가능). 따라서 가능한 동안 C#에서 웹 서비스 클래스를 생성할 수 있어야 합니다. 런타임 시 동적으로 메서드를 추가하고 제거합니다.
이제 지금까지 생각해낼 수 있었던 최고의 계획은 (런타임) 웹 서비스를 나타내는 C# 코드를 생성하고 System.Reflection.Emit를 사용하여 이를 컴파일한 다음 런타임에 어셈블리를 로드하는 것입니다. 이 모든 것은 스크립트가 추가될 때마다 수행됩니다. 또는 서비스와의 메소드를 제거합니다(자주 발생해서는 안 됩니다).
이것보다 더 좋은 아이디어를 가진 사람이 있나요?
해결책
다음을 사용하여 WSDL을 수정할 수 있습니다. 비누확장반사경 수업.에서 커크 에반스 블로그:
서비스에 대한 WSDL 정의를 제공하기 위해 유형이 반영될 때 SoapExtensionReflector가 호출됩니다.이 유형을 활용하여 리플렉션 호출을 가로채고 WSDL 출력을 수정할 수 있습니다.
다음 예에서는 2개의 웹 서비스 메서드 중 첫 번째 메서드를 제거합니다.
[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;
}
}
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);
}
}
}
}
web.config의 구성/system.web 섹션에 다음을 추가합니다.
<webServices>
<soapExtensionReflectorTypes>
<add type="TestWebservice.MyReflector, TestWebservice" />
</soapExtensionReflectorTypes>
</webServices>
이는 WSDL 문서에서 메소드를 동적으로 제거하기 위한 시작점을 제공합니다.또한 비활성화된 경우 웹 메서드에서 NotImplementedException을 발생시켜야 합니다.
마지막으로 ?WSDL 매개변수 없이 .asmx 엔드포인트를 호출하여 생성된 웹 서비스 문서를 비활성화해야 합니다.wsdlHelpGenerator 요소의 href 속성을 일부 URL로 설정합니다.DefaultWsdlHelpGenerator.aspx를 자체 문서 처리기의 시작점으로 사용할 수 있습니다.웹 서비스 문서에 대한 질문을 참조하세요. XML 파일, 2002년 8월.
다른 팁
XMLRPC는 상당히 죽었습니까?
비누는 WSDL을 암시합니다. WSDL을 어떻게 동적으로 생성합니까?
WCF를 사용하여 조사해야합니다. WSDL (및 기타 메타 데이터)을 생성하는 프로세스를 제어 할 수있을 것으로 기대하지만, 들어오는 메시지의 처리를 제어 할 수 있어야합니다. 특히, 들어오는 메시지를 검사하여 실행할 스크립트, 전달할 매개 변수 등을 결정할 수 있습니다.
입력 및 출력 유형의 WCF 서비스를 만들 수 있습니다. xs:any
들어오는 요청을 원시로 처리하십시오 Message
. 그러면 모든 유형의 데이터를 수락하고 모든 유형의 데이터를 반환 할 수 있습니다. 데이터 계약이나 정적 유형을 사용하지 않고 Message
그리고 a Message
밖으로.
이 접근법의 문제점은 WSDL에서 프록시를 생성하는 것이 실제로 래퍼를 제공하는 것 외에는 소비자가 방법을 호출하는 데 도움이되지 않는다는 것입니다. 이 방법에 허용되는 데이터를 제공하려면 손으로 바르는 데이터 유형 등이 필요하지 않으므로 어려운 계약만큼 직관적이지 않습니다.
비누 인터페이스 여야합니까? 그것은 경로/REST/etc 기반 API에 더 적합한 것처럼 들립니다. ASP.NET MVC에서 무언가를 할 수 있습니다 (사용자 정의 포함 IController.Execute
방법으로 작업을 해결하는 방법)는 아주 쉽게 (사실, 나는 매우 유사한 일을하고 있습니다. 내 코드 중 일부 현재).
예를 들어, 노선이있을 수 있습니다.
http://myserver/myservice/mymethod
이는 (신체 또는 args에서) 페이로드 (매개 변수)를 받아들이고 결과를 응답에 반환합니다. 비 MVC에서는 와일드 카드 매핑 된 일반 핸들러와 비슷한 일을 할 수 있어야합니다.
다음은 제안입니다.
- WCF를 사용하십시오.
다음 블로그 게시물에서 정보를 사용하여 WCF에서 WSDL을 만듭니다.
http://www.pluralsight.com/community/blogs/kirillg/archive/2006/06/18/28380.aspx
그런 다음 MEX를 사용 하여이 정보를 게시 할 수 있습니다.
그런 다음 고객이 메타 데이터를로드하고 서비스를 호출 할 수 있도록 서비스가 열려 있습니다.