是否可以创建完全包含在.svc文件中的ASP.NET Web服务?

时间:2010-12-03 16:38:11

标签: c# asp.net web-services

是否可以创建“插入式”Web服务?我想要做的是创建一个.svc文件,该文件可以放在IIS上的Web目录中,并通过其URL访问(和执行),而无需安装任何其他文件,也无需更改任何配置文件。

我正在研究允许上传.svc文件的Web应用程序中可能存在的安全问题。如果可以上载然后执行.svc文件,这对于此应用程序来说将是一个很大的安全问题。不幸的是,我不是.NET开发人员,所以我可能在这里遗漏了很多东西。

我知道可以在“服务主机”指令之后将服务接口和实现直接放入.svc文件中。这是我的.svc文件:

<%@ ServiceHost Language = "C#" Debug = "true" Service = "EchoService" %>
public interface IEchoService
{
    string Hello();
}

public class EchoService : IEchoService
{
    public string Hello()
    {
        return "Hello";
    }
}

现在当我访问http://localhost/test1.svc时,我从.NET得到一个例外:服务'EchoService'没有应用程序(非基础架构)端点。这可能是因为没有为您的应用程序找到配置文件,或者因为在配置文件中找不到与服务名称匹配的服务元素,或者因为在service元素中没有定义端点。

据我所知,通常您应该在web.config或app.config文件中配置Web服务端点。从一些谷歌搜索我还了解到,可以通过定义自己的ServiceHost和ServiceCodeFactory以编程方式配置端点。我找到了一些例子,但无法使它们正常工作。

如果有人可以告诉我“不,你想要做什么是不可能的,因为......”我会非常感激,或者说明如何在上面的例子中添加必要的代码以获得可执行服务。< / p>

更新:使用Josh的建议我终于让它运转了。请参阅下面的答案,了解工作代码。

2 个答案:

答案 0 :(得分:1)

好的,我有一个包含在.svc文件中的工作SOAP Web服务。这是代码:

<%@ ServiceHost 
    Language = "C#" 
    Debug = "true" 
    Factory="Hello.CustomServiceHostFactory" 
    Service = "Hello.HelloService" %>

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace Hello
{

    public class CustomServiceHostFactory : ServiceHostFactory
    {

   public override System.ServiceModel.ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
   {
       return base.CreateServiceHost(constructorString, baseAddresses);
   }

       protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
       {
       CustomHost host = new CustomHost(serviceType, baseAddresses);

           //configure customServiceHost here

       host.AddServiceEndpoint(typeof(IHelloService), new BasicHttpBinding(), "");

           var smb = host.Description.Behaviors.Find <System.ServiceModel.Description.ServiceMetadataBehavior>(); 
           if(smb == null)
           {
           // add the "get metadata" behavior 
           // This will allow the service to emit WSDL when tickled at the right HTTP endpoint
           smb= new System.ServiceModel.Description.ServiceMetadataBehavior();
           smb.HttpGetEnabled = true;
           host.Description.Behaviors.Add(smb);
           }    
               return host;
       }
    }

public class CustomHost : ServiceHost
{

  public CustomHost()
  {
  }

  public CustomHost(Type serviceType, params Uri[] baseAddresses)
    : base(serviceType, baseAddresses)
  {
  }


  public CustomHost(object singeltonInstance, params Uri[] baseAddresses)
        : base(singeltonInstance, baseAddresses)
{
} 

  protected override void ApplyConfiguration()
  {
     base.ApplyConfiguration();
  }
}

[ServiceContract(Namespace="http://www.example.com")]
public interface IHelloService
{
[OperationContract]
   string Hello();
}

public class HelloService : IHelloService
{
   public string Hello() {
        return "Hello";
   }
}
}

它适用于.NET 4,不确定以前的版本。

答案 1 :(得分:0)

我以前从未这样做过,但可能的解决方案是拥有ServiceHost工厂。我相信(不自己尝试)您可以通过使用自定义服务主机公开的方法以编程方式配置ServiceHost

http://msdn.microsoft.com/en-us/library/bb332338.aspx

向下滚动到在IIS中访问ServiceHost

清单5-6。带有CustomServiceHostFactory

的.svc文件
<% @ServiceHost Language="C#" Debug="true"
Service="QuickReturns.StockTrading.ExchangeService.TradeService"
Factory="QuickReturns.StockTrading.ExchangeService.
TradeServiceCustomHostFactory" %>

清单5-7。 TradeServiceCustomHostFactory和TradeServiceCustomHost

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace QuickReturns.StockTrading.ExchangeService
{
   public class TradeServiceCustomHostFactory : ServiceHostFactory
   {
      protected override ServiceHost CreateServiceHost(
         Type serviceType, Uri[] baseAddresses)
      {
         TradeServiceCustomHost customServiceHost =
            new TradeServiceCustomHost(serviceType, baseAddresses);

         //configure customServiceHost here

         return customServiceHost;
      }
   }

   public class TradeServiceCustomHost : ServiceHost
   {
      public TradeServiceCustomHost(Type serviceType, params Uri[] 
baseAddresses)
         : base(serviceType, baseAddresses)
      {
          //or configure here
      }

      protected override void ApplyConfiguration()
      {
         base.ApplyConfiguration();
      }
   }
}

您可以将所有这些放入一个svc。