Skip to main content
 首页 » 编程设计

c#之伪造的 ASMX Web 服务调用

2024年02月24日48lautakyan007

我构建了一个连接到 SQL Server 数据库的 .NET ASMX Web 服务。有一个 Web 服务调用 GetAllQuestions()。

 var myService = new SATService(); 
 var serviceQuestions = myService.GetAllQuestions(); 

我将GetAllQuestions的结果保存到本地应用程序文件夹中的GetAllQuestions.xml

有没有办法伪造网络服务调用并使用本地 xml 结果?

我只想获取我的整个 sql 表的内容,并像使用 LINQ to SQL Web 服务一样自动为我生成具有相关属性名称的对象数组。

请记住,我正在构建一个独立的 Monotouch iPhone 应用程序。

请您参考如下方法:

使用dependency injection .

//GetSATService returns the fake service during testing      
var myService = GetSATService();  
var serviceQuestions = myService.GetAllQuestions(); 

或者,最好在对象的构造函数中设置 SATService 字段(因此构造函数需要设置 SATService。如果这样做,将更容易测试。

编辑:抱歉,我会在这里详细说明。您在上面的代码中拥有的是耦合依赖关系,您的代码在其中创建它正在使用的对象。依赖注入(inject)或控制反转 (IOC) 模式会让您解耦该依赖关系。 (或者简单地说,不要称之为"new"——让其他东西来做——你可以在消费者之外控制的东西。)

有几种方法可以做到这一点,如下代码所示(注释解释):

class Program 
{ 
    static void Main(string[] args) 
    { 
        //ACTUAL usage 
        //Setting up the interface injection 
        IInjectableFactory.StaticInjectable = new ConcreteInjectable(1); 
 
        //Injecting via the constructor 
        EverythingsInjected injected =  
            new EverythingsInjected(new ConcreteInjectable(100)); 
 
        //Injecting via the property 
        injected.PropertyInjected = new ConcreteInjectable(1000); 
 
        //using the injected items 
        injected.PrintInjectables(); 
        Console.WriteLine(); 
 
        //FOR TESTING (normally done in a unit testing framework) 
        IInjectableFactory.StaticInjectable = new TestInjectable(); 
        EverythingsInjected testInjected =  
            new EverythingsInjected(new TestInjectable()); 
        testInjected.PropertyInjected = new TestInjectable(); 
        //this would be an assert of some kind 
        testInjected.PrintInjectables();  
 
        Console.Read(); 
    } 
 
    //the inteface you want to represent the decoupled class 
    public interface IInjectable { void DoSomething(string myStr); } 
 
    //the "real" injectable 
    public class ConcreteInjectable : IInjectable 
    { 
        private int _myId; 
        public ConcreteInjectable(int myId) { _myId = myId; } 
        public void DoSomething(string myStr) 
        { 
            Console.WriteLine("Id:{0} Data:{1}", _myId, myStr); 
        } 
    } 
 
    //the place to get the IInjectable (not in consuming class) 
    public static class IInjectableFactory 
    { 
        public static IInjectable StaticInjectable { get; set; } 
    } 
 
    //the consuming class - with three types of injection used 
    public class EverythingsInjected 
    { 
        private IInjectable _interfaceInjected; 
        private IInjectable _constructorInjected; 
        private IInjectable _propertyInjected; 
 
        //property allows the setting of a different injectable 
        public IInjectable PropertyInjected 
        { 
            get { return _propertyInjected; } 
            set { _propertyInjected = value; } 
        } 
 
        //constructor requires the loosely coupled injectable 
        public EverythingsInjected(IInjectable constructorInjected) 
        { 
            //have to set the default with property injected 
            _propertyInjected = GetIInjectable(); 
 
            //retain the constructor injected injectable 
            _constructorInjected = constructorInjected; 
 
            //using basic interface injection 
            _interfaceInjected = GetIInjectable(); 
        } 
 
        //retrieves the loosely coupled injectable 
        private IInjectable GetIInjectable() 
        { 
            return IInjectableFactory.StaticInjectable; 
        } 
 
        //method that consumes the injectables 
        public void PrintInjectables() 
        { 
            _interfaceInjected.DoSomething("Interface Injected"); 
            _constructorInjected.DoSomething("Constructor Injected"); 
            _propertyInjected.DoSomething("PropertyInjected"); 
        } 
    } 
 
    //the "fake" injectable 
    public class TestInjectable : IInjectable 
    { 
        public void DoSomething(string myStr) 
        { 
            Console.WriteLine("Id:{0} Data:{1}", -10000, myStr + " For TEST"); 
        } 
    } 

以上是一个完整的控制台程序,您可以运行并使用它来了解其工作原理。我尽量保持简单,但如有任何问题,请随时问我。

第二次编辑: 从评论中可以看出,这是一个操作需求,而不是测试需求,所以实际上它是一个缓存。这是一些可用于预期目的的代码。同样,下面的代码是一个完整的工作控制台程序。

class Program 
{ 
    static void Main(string[] args) 
    { 
        ServiceFactory factory = new ServiceFactory(false); 
        //first call hits the webservice 
        GetServiceQuestions(factory); 
        //hists the cache next time 
        GetServiceQuestions(factory); 
        //can refresh on demand 
        factory.ResetCache = true; 
        GetServiceQuestions(factory); 
        Console.Read(); 
    } 
 
    //where the call to the "service" happens 
    private static List<Question> GetServiceQuestions(ServiceFactory factory) 
    { 
        var myFirstService = factory.GetSATService(); 
        var firstServiceQuestions = myFirstService.GetAllQuestions(); 
        foreach (Question question in firstServiceQuestions) 
        { 
            Console.WriteLine(question.Text); 
        } 
        return firstServiceQuestions; 
    } 
} 
 
//this stands in place of your xml file 
public static class DataStore 
{ 
    public static List<Question> Questions; 
} 
 
//a simple question 
public struct Question 
{ 
    private string _text; 
    public string Text { get { return _text; } } 
    public Question(string text) 
    { 
        _text = text; 
    } 
} 
 
//the contract for the real and fake "service" 
public interface ISATService 
{ 
    List<Question> GetAllQuestions(); 
} 
 
//hits the webservice and refreshes the store 
public class ServiceWrapper : ISATService 
{ 
    public List<Question> GetAllQuestions() 
    { 
        Console.WriteLine("From WebService"); 
        //this would be your webservice call 
        DataStore.Questions = new List<Question>() 
                   { 
                       new Question("How do you do?"),  
                       new Question("How is the weather?") 
                   }; 
        //always return from your local datastore 
        return DataStore.Questions; 
    } 
} 
 
//accesses the data store for the questions 
public class FakeService : ISATService 
{ 
    public List<Question> GetAllQuestions() 
    { 
        Console.WriteLine("From Fake Service (cache):"); 
        return DataStore.Questions; 
    } 
} 
 
//The object that decides on using the cache or not 
public class ServiceFactory 
{ 
    public  bool ResetCache{ get; set;} 
    public ServiceFactory(bool resetCache) 
    { 
        ResetCache = resetCache; 
    } 
    public ISATService GetSATService() 
    { 
        if (DataStore.Questions == null || ResetCache) 
            return new ServiceWrapper(); 
        else 
            return new FakeService(); 
    } 
} 

希望这对您有所帮助。祝你好运!