// // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // .Net StockTrader Sample WCF Application for Benchmarking, Performance Analysis and Design Considerations for Service-Oriented Applications //====================================================================================================== // Code originally contributed by Microsoft Corporation. // This contribution to the Stonehenge project is limited strictly // to the source code that is submitted in this submission. // Any technology, including underlying platform technology, // that is referenced or required by the submitted source code // is not a part of the contribution. // For example and not by way of limitation, // any systems/Windows libraries (WPF, WCF, ASP.NET etc.) // required to run the submitted source code is not a part of the contribution //====================================================================================================== // ITradeServiceFacadeWcf: The Wcf/.NET 3.5 Web Service facade Interface for business service // operations in Trade.BusinessServices.TradeService.cs class. Please note well that // to maintain compatibility with IBM WebSphere Trade 6.1 web services, this service facade // provides NO authentication mechanism and limited input validation. This is to preserve // interoperability and also for fair benchmark comparison purposes. These service operations would // require authentication (and possibly non-repudiation) if deployed across the Internet; but perhaps would // not if deployed as part of an Inranet application. // It's easy to see why: In the current implementation we have our ASP.NET Web // Application using ASP.NET forms authentication mechanism to ensure only // registered users can access the site (and even this could/should be locked down further with ASP.NET's // built-in encryption capabilities and by using SSL if you wanted to deploy to the Internet). // But the business services are 'independent' of this client application--and can be accessed, for instance, // by other clients and potentially other organizaitons (for example, the Trade 6.1 JSP Web Application). // Suffice it to say that this facade for now is (possibly) suitable for deployment on the intranet, but not on // the Internet. Web Service security and security in general are deep topics. // Two good starting Web Service security resources can be found at: // http://msdn2.microsoft.com/en-us/library/ms732008.aspx // and http://msdn.microsoft.com/msdnmag/issues/07/02/ServiceStation/default.aspx // After skimming the content at the first link above, it should become clear that WCF incorporates a wide variety of mechanisms and standards // for authentication and general service security patterns. The second link is about the // Patterns and Practices Group at Microsoft, and work going on to define a Service Software Factory that // can help automate and structure various elements of a WCF service, including security, from within Visual Studio. // Also, our actual service implementation methods (in TradeService.cs) could have multiple WCF facades, // each with various different levels/techniques for authentication. // It's the facade that is hosted (either in IIS or a self-host service or .exe), and it would be easy with // WCF to create a second facade for the business service methods in TradeService.cs that required much // tighther security; it would be this facade that would get exposed by it's specific host to the 'outside' world, // and not necessarily this less secure facade that mimicks the WebSphere Trade 6.1 Web Service interfaces and does no // authentication. using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.ServiceModel; using System.ServiceModel.Channels; using System.Configuration; using System.Diagnostics; using System.ServiceModel.Dispatcher; using System.ServiceModel.Description; using System.Xml; using Trade.BusinessServiceDataContract; namespace Trade.BusinessServiceContract { //This begins the definition of the WCF Service Contract, a fundamental concept within WCF for //maintaining interfaces between services within a composite, SOA application, while //hiding implementation details from service consumers. // //Note the IBM namespace is used to allow the Trade 6.1 WebSphere application, out-of-the-box, to //have bi-directional interoperability with .NET StockTrader. The IBM proxy expects this namespace, so our //service emits it (and hence our WCF client receives it). Interoperability works //without any code changes to IBM WebSphere Trade 6.1; simply point the endpoint for Trade 6.1 Web Services //at the Asmx or WCF Web Services (either self hosted or IIS-hosted). The converse also works- //point the ASP.NET StockTrader application at the backend Trade 6.1/WebSphere services via the //AccessMode=WebSphere_WebService setting in Web.Config after setting the correct endpoint to //your WebSphere server running Trade 6.1 in the same config file. /// /// This is the service contract for Trade Business Services. It defines the business service layer operations /// that are separately implemented in an implementation class. /// [ServiceContract(Namespace = "http://trade.samples.websphere.ibm.com")] public interface ITradeServices { [OperationContract(Action = "")] void emptyMethodAction(); [OperationContract(Action="isOnline", Name="isOnline", IsOneWay=true)] void isOnline(); [OperationContract()] [return: MessageParameter(Name = "loginReturn")] AccountDataModel login(string userID, string password); [OperationContract(Action = "getOrders")] [ServiceKnownType(typeof(OrderDataModel))] [return: MessageParameter(Name = "getOrdersReturn")] List getOrders(string userID); [OperationContract(Action = "getAccountData")] [return: MessageParameter(Name = "getAccountDataReturn")] AccountDataModel getAccountData(string userID); [OperationContract(Action = "getAccountProfileData")] [return: MessageParameter(Name = "getAccountProfileDataReturn")] AccountProfileDataModel getAccountProfileData(string userID); [OperationContract(Action = "updateAccountProfile")] [return: MessageParameter(Name = "updateAccountProfileReturn")] AccountProfileDataModel updateAccountProfile(AccountProfileDataModel profileData); [OperationContract(Action = "logout")] [return: MessageParameter(Name = "logoutReturn")] void logout(string userID); [OperationContract(Action = "buy")] [return: MessageParameter(Name = "buyReturn")] OrderDataModel buy(string userID, string symbol, double quantity, int orderProcessingMode); [OperationContract(Action = "sell")] [return: MessageParameter(Name = "sellReturn")] OrderDataModel sell(string userID, int holdingID, int orderProcessingMode); [OperationContract(Action = "getHoldings")] [ServiceKnownType(typeof(HoldingDataModel))] [return: MessageParameter(Name = "getHoldingsReturn")] List getHoldings(string userID); [OperationContract(Action = "register")] [return: MessageParameter(Name = "registerReturn")] AccountDataModel register(string userID, string password, string fullname, string address, string email, string creditcard, decimal openBalance); [OperationContract(Action = "getClosedOrders")] [ServiceKnownType(typeof(OrderDataModel))] [return: MessageParameter(Name = "getClosedOrdersReturn")] List getClosedOrders(string userID); [OperationContract(Action = "getMarketSummary")] [ServiceKnownType(typeof(QuoteDataModel))] [return: MessageParameter(Name = "getMarketSummaryReturn")] MarketSummaryDataModelWS getMarketSummary(); [OperationContract(Name = "getQuote")] [return: MessageParameter(Name = "getQuoteReturn")] QuoteDataModel getQuote(string symbol); [OperationContract(Action = "getHolding")] [return: MessageParameter(Name = "getHoldingReturn")] HoldingDataModel getHolding(string userID, int holdingID); [OperationContract(Action = "getTopOrders")] [ServiceKnownType(typeof(OrderDataModel))] [return: MessageParameter(Name = "getTopOrdersReturn")] List getTopOrders(string userID); [OperationContract(Action = "sellEnhanced")] [return: MessageParameter(Name = "sellEnhancedReturn")] OrderDataModel sellEnhanced(string userID, int holdingID, double quantity); } }