WCF post方法实现

时间:2012-03-21 10:25:31

标签: c# sql ajax wcf post

我有一个WCF服务,它连接到从移动应用程序调用的sql server数据库。我有以下方法来帮助创建预订。

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();
    }

标记:

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

配置文件:

<?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>

接口:

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

    void CreateBooking(Booking booking); 
}

预订课程:

[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; }

}

然而,每当我调用该方法时,我都会收到405错误。我的问题是,上面的方法是导致错误还是连接结束的事情?感谢。

2 个答案:

答案 0 :(得分:2)

当您在IIS中托管WCF服务时,address属性会从IIS中托管的.svc文件的位置推断出来,因此它应该为空或相对地址:

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

基本地址将由IIS和您托管应用程序的站点提供。因此,它将指向IIS中托管的RoomBookingService.svc文件的位置。

当我查看以下代码时:

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

SqlCommand cmd = new SqlCommand(command, sql);
我的眼睛开始流血。你绝对不应该写任何类似的代码。处理SQL时始终使用参数化查询。您的代码容易受到SQL injection的攻击。<​​/ p>

所以:

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();
    }
}

现在您可以调用此服务。例如,使用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) {

    }
});

答案 1 :(得分:2)

我已经尝试了上面的场景,并且几乎没有任何变化,我得到了它如下所示:

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

您可以删除WrappedRequest设置,因为您只有1个参数。

当我使用以下请求从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}

您也可以删除OperationContract中的name属性。如果您在IIS中托管,则地址可以为空,因为IIS已分配地址。