简体   繁体   English

WCF后方法实现

[英]WCF post method implementation

I have a WCF service which is connected to an sql server database which is called from a mobile application. 我有一个WCF服务,该服务连接到从移动应用程序调用的sql服务器数据库。 I have the following method which helps create bookings. 我有以下方法可以帮助创建预订。

public void CreateBooking(Booking booking)
    {
        Booking newbooking = new Booking();
        sql = new SqlConnection("Data Source=comp;Initial Catalog=BookingDB;Integrated Security=True");
        sql.Open();

        string command =
            ("INSERT INTO Bookings( BookingName, BookingStart, BookingEnd, RoomID ) " +
             "VALUES ("
                + "'" + booking.BookingName + "'" + ", "   
                + "'" + booking.BookingStart  + "'" + ", " 
                + "'" + booking.BookingEnd + "'" + ", "
                        + booking.RoomID + ")");

        SqlCommand cmd = new SqlCommand(command, sql);                
        cmd.ExecuteNonQuery();            
    }

    public void Close()
    {
        sql.Close();
    }

Markup: 标记:

<%@ ServiceHost Language="C#" Debug="true" Service="BookingServices.BookingService" CodeBehind="BookingService.svc.cs" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Config File: 配置文件:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <!--<authentication mode="None"/>-->
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
      </assemblies>
    </compilation>
  </system.web>
  <system.serviceModel>
<services>
  <service name="RoomBookingServices.RoomBookingService" behaviorConfiguration="RoomBookingServiceBehaviour">
    <endpoint address="http://192.168.0.4:6321/RoomBookingServices/RoomBookingService.svc" binding="webHttpBinding" bindingConfiguration="webHttpBindingWithJsonP" contract="RoomBookingServices.IRoomBookingService" behaviorConfiguration="webHttpBehavior">
      <identity>
        <servicePrincipalName value=""/>
      </identity>
    </endpoint>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="RoomBookingServiceBehaviour">
      <!-- To avoid disclosing metadata information, 
      set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="true" />
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  
      Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true" />
       </behavior>
     </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="webHttpBehavior">
         <webHttp />
    </behavior>
  </endpointBehaviors>
</behaviors>
<bindings>
  <webHttpBinding>
    <binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true"></binding>
  </webHttpBinding>
</bindings>
<!--<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />-->
<!--<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />-->
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>
  <connectionStrings>
    <add name="RoomBookingDatabaseEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=HAL;initial catalog=RoomBookingDatabase;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
    <add name="RoomBookingDatabaseEntities1" connectionString="metadata=res://*/RoomBookingDB.csdl|res://*/RoomBookingDB.ssdl|res://*/RoomBookingDB.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=HAL;initial catalog=RoomBookingDatabase;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

Interface: 接口:

[OperationContract(Name="postmethod")]
    [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, UriTemplate = "postmethod/new")]

    void CreateBooking(Booking booking); 
}

Booking class: 预订舱位:

[DataContract]
public class Booking
{
    [DataMember]
    public int BookingID { get; set; }

    [DataMember]
    public string BookingName { get; set; }

    [DataMember]
    public DateTime BookingStart { get; set; }

    [DataMember]
    public DateTime BookingEnd { get; set; }

    [DataMember]
    public int RoomID { get; set; }

}

However, whenever I call the method I am getting a 405 error. 但是,每当我调用该方法时,都会出现405错误。 My question is, is the method above causing the error or is it something in the connection end of things? 我的问题是,上面的方法是导致错误还是在连接的末端? Thanks. 谢谢。

When you are hosting a WCF service in IIS the address attribute is inferred from the location to the .svc file as hosted in IIS so it should either empty or a relative address: 当您在IIS中托管WCF服务时, address属性是从位置推断为IIS中托管的.svc文件,因此它应该为空或相对地址:

<service name="RoomBookingServices.RoomBookingService" behaviorConfiguration="RoomBookingServiceBehaviour">
    <endpoint 
        address="" 
        binding="webHttpBinding" 
        bindingConfiguration="webHttpBindingWithJsonP"
        contract="RoomBookingServices.IRoomBookingService" 
        behaviorConfiguration="webHttpBehavior">
    </endpoint>
</service>

The base address will be provided by IIS and the site where you are hosting your application under. 基本地址将由IIS和您托管应用程序的站点提供。 So it will point to the location of the RoomBookingService.svc file as hosted in IIS. 因此,它将指向IIS中托管的RoomBookingService.svc文件的位置。

Also when I look at the following code: 另外,当我看下面的代码时:

string command =
        ("INSERT INTO Bookings( BookingName, BookingStart, BookingEnd, RoomID ) " +
         "VALUES ("
            + "'" + booking.BookingName + "'" + ", "   
            + "'" + booking.BookingStart  + "'" + ", " 
            + "'" + booking.BookingEnd + "'" + ", "
                    + booking.RoomID + ")");

SqlCommand cmd = new SqlCommand(command, sql);

my eyes start to bleed. 我的眼睛开始流血。 You should absolutely never write any code like that. 您绝对不应编写任何类似的代码。 Always use parametrized queries when dealing with SQL. 处理SQL时,请始终使用参数化查询。 Your code is vulnerable to SQL injection . 您的代码容易受到SQL注入的攻击。

So: 所以:

public void CreateBooking(Booking booking)
{
    using (var conn = new SqlConnection("Data Source=comp;Initial Catalog=BookingDB;Integrated Security=True"))
    using (var cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = 
        @"INSERT INTO 
          Bookings( BookingName, BookingStart, BookingEnd, RoomID ) 
          VALUES ( @BookingName, @BookingStart, @BookingEnd, @RoomID )";

        cmd.Parameters.AddWithValue("@BookingName", booking.BookingName);
        cmd.Parameters.AddWithValue("@BookingStart", booking.BookingStart);
        cmd.Parameters.AddWithValue("@BookingEnd", booking.BookingEnd);
        cmd.Parameters.AddWithValue("@RoomID", booking.RoomID);
        cmd.ExecuteNonQuery();
    }
}

And now you could invoke this service. 现在您可以调用此服务。 For example using jQuery AJAX: 例如使用jQuery AJAX:

$.ajax({
    url: '/RoomBookingService.svc/postmethod/new',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({ 
        booking: {
            BookingID: 1,
            BookingName: 'bn',
            BookingStart: '/Date(1232739449000+0000)/',
            BookingEnd: '/Date(1232776449000+0000)/',
            RoomID: 2
        }
    }),
    success: function (result) {

    }
});

I have tried the above scenario and with few changes i got it working as shown below: 我已经尝试了上述方案,并做了一些改动,如下所示:

[OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, UriTemplate = "postmethod/new")]
        Booking CreateBooking(Booking booking); 

You can remove the WrappedRequest setting as you just have only 1 param. 您可以删除WrappedRequest设置,因为您只有1个参数。

When i perform a POST from Fidder with the below request i get a successful response: 当我通过以下请求从Fidder执行POST时,我会收到成功的响应:

POST http://localhost/SampleApp/Service1.svc/postmethod/new HTTP/1.1
Content-Type: application/json
Host: localhost
Content-Length: 144
Expect: 100-continue

{"BookingEnd":"\/Date(1332420656202+0000)\/","BookingID":1,"BookingName":"client sent","BookingStart":"\/Date(1332334256202+0000)\/","RoomID":2}

You can remove the name attribute in the OperationContract as well. 您也可以在OperationContract中删除name属性。 If you are hosting in IIS then the address can be empty as the address is assigned by IIS. 如果您在IIS中托管,则该地址可以为空,因为该地址是由IIS分配的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM