Setting the WebServiceWrapper endpointURI at run time - apache-flex

I'm in the middle of switching from Flex Builder 3 to Flash Builder 4, and one of the problems I have run into is that support for web services in 4 is substantially different. In both IDE's I am able to import a WSDL for my web service and it will generate the appropriate client classes for communicating with the service. The generated code in each is different.
In my Flex3 code I was able to access the endpointURI property of the mx.rpc.soap.AbstractWebService, but in the Flex4 code that is generated, the new class extends com.adobe.fiber.services.wrapper.WebServiceWrapper which does not have the endpointURI property.
My project has mulitple game servers and the player picks which server they want to play on. In the past if the player wanted server 1, I would set the endpoint URI to http://game1.server.com/service.asmx, and like wise if they wanted server 2 I would set the endpoint to http://game2.server.com/service.asmx.
What am I looking for to accomplish this in Flash Builder 4?

Short Answer:
var s:ClassThatExtendsWebServiceWrapper = new ClassThatExtendsWebServiceWrapper;
s.serviceControl.endpointURI = 'http://service.com/service.asmx';
Long Answer:
Well I finally found a solution. Adobe seems to have made this much harder than it should have been.
Web Service classes that are generated by Flash Builder 4 extend the com.adobe.fiber.services.wrapper.WebServiceWrapper. WebServiceWrapper has a property called serviceControl that can be used to control the service. The problem is that not all the members of serviceControl are accessible at the application code level. Lets assume that I have a web service called GameService. When I use the data tool to connect to the web service by providing a WSDL, Flash Builder will create two classes for me automcatically.
internal class _Super_GameService extends
com.adobe.fiber.services.wrapper.WebServiceWrapper
{ ... }
public class GameService extends _Super_GameService
{}
_Super_GameService contains all the automatically generated code to make calls to the web service. GameService contains no code itself, but unlike _Super_GameService, it is public. The idea here is that any enhancements that we need to make can be made to GameService, then later on if we need to update, _Super_GameService can be regenerated, but out changes to GameService will not be overwritten by the code generation tool.
Now this leads us to usage of these generated classes. Typically all I should have to do is create an instance of GameService and call a method on it. In this example DoSomethingAwesome is a method available on the web service.
var gs:GameService = new GameService();
var token:AsyncToken = gs.DoSomethingAwesome();
Now this will call the service using the URI of the service specified in the WSDL file. In my situation I wanted GameService to connect to a different URI. This should have been simple, but things fell apart.
My first problem was that viewing the documentation on WebServiceWrapper (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/com/adobe/fiber/services/wrapper/WebServiceWrapper.html) did not render properly in Firefox. So when I was reading the documentation I wasn't getting the full picture. This really needs to be fixed by Adobe.
Viewing the documentation in another browser helped me find out about the serviceControl property of WebServiceWrapper. serviceControl is declared as a mx.rpc.soap.AbstractWebService. AbstractWebService does have an endpointURI property which makes the following code valid.
var gs:GameService = new GameService();
gs.serviceControl.endpointURI = 'http://game1.service.com/GameService.asmx';
The other problem I had is that for some reason the endpointURI property of serviceControl does not appear in the Intellisense context menu. So since I didn't see serviceControl in the online documentation at first, and I didn't see endpointURI in intellisense, I didn't realize the property was there to be set.
If you look at the source for AbstractWebserivce, (http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/frameworks/projects/rpc/src/mx/rpc/soap/AbstractWebService.as) there doesn't seem to be an Exclude tag to explain why endpointURI does not appear in the Intellisense context menu. So I don't know what is going on there.

You should be able to override the endpointURI on the WebService. But I'm not sure where to do that with the generated code since I use <s:WebService/>.

This is the only way I could get it to work, in the generated stub for your service:
import com.adobe.fiber.core.model_internal;
Also:
/**
* Override super.init() to provide any initialization customization if needed.
*/
protected override function preInitializeService():void
{
_needWSDLLoad = false; // to prevent loading the default WSDL
super.preInitializeService();
// Initialization customization goes here
wsdl = "http://localhost/yourservice?wsdl";
_needWSDLLoad = true;
model_internal::loadWSDLIfNecessary();

Related

how to resolve the type or namespace "HttpContextBase " could not be found in ASP.Net class library in a new class library i created

public class BasketService
{
IRepositoryBase baskets;
public const string BasketSession = "eCommerceBasket";
public BasketService(IRepositoryBase<Basket> baskets)
{
this.baskets = baskets;
}
private Basket CreateNewBasket(HttpContextBase httpContext)
{
}
}
If this is really what you want...
The HttpContextBase class is in the System.Web namespace. So you'll either need to fully-qualify the class name:
private Basket CreateNewBasket(System.Web.HttpContextBase httpContext)
{
}
or add the appropriate using directive at the top of your code file:
using System.Web;
If you then get an error that HttpContextBase isn't in that namespace or that the namespace doesn't exist, double-check that you've added the reference to your project. In the Solution Explorer in Visual Studio, right-click on the "References" node in the project and select "Add Reference". Navigate to the "Assemblies" to find and select System.Web. Click "OK".
Having said that... Are you sure this is the design you want? If your goal is to make a generic service which can be used by different applications, making that service depend on the web application would be ill-advised. What happens if you want to use it in a Console Application? There's no web context there.
Instead of making your general-purpose code depend on UI-specific things, turn that around. Make your UI-specific applications depend on the general-purpose code. So for this particular method, ask yourself...
What would I need to "create" a new "basket"?
Whatever information that is, that's what CreateNewBasket should accept as parameters. Maybe it's a handful of values, maybe it's a custom object, that's up to you. But "creating a basket" does not require an HTTP context. It requires some values that you are expecting to find in your HTTP context at a particular time.
The application layer should be responsible for pulling those values from the HTTP context and providing them to CreateNewBasket. The general-purpose code should just require the values themselves.

ASP.Net MVC 6: Recursive Dependency Injection

Still exploring the new ASP.NET MVC5, now with build in DI!
No Problem so far, I can just inject my Handlers (I don't like the Term Service, since this defines to me a Platform-Neutral Interface):
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<Model.Meta.AppSettings>(Configuration.GetSection("AppSettings"));
services.AddSingleton(typeof(Logic.UserEndPointConfigurationHandler));
services.AddSingleton(typeof(Logic.NetworkHandler));
services.AddMvc();
}
Works fine, also the strongly typed Configuration-Object "AppSettings" works perfectly fine.
Also the Injection in the Controllers works as well.
But now my collaps: I seperated my DataAccess from the Handlers, and obviously I'd like to inject them as well:
public class UserEndPointConfigurationHandler
{
private readonly DataAccess.UserEndPointAccess _access;
public UserEndPointConfigurationHandler(DataAccess.UserEndPointAccess access)
{
_access = access;
}
But bam, UserEndPointAccess can't be resolved. So it seems like even I directly request to DI an Class with a Parameterless-Constructor, I need to register that. For this case, sure I should Interface and register them, but what does that mean for internal helper classes I also inject?
According to the Docs: http://docs.asp.net/en/latest/fundamentals/dependency-injection.html#recommendations and also the examples I found, all people in the world only seem to communicate between Controllers and some Repositories. No Business-Layer and no Classes on different Abstraction-Levels in Assemblies.
Is the Microsoft DI approach something totally differnt than the good ol' Unity one, where I can really decouple as fine granular as I'd like to?
Thanks in advance.
Matthias
Edit #Nightowl: I add my answer here, since it's a bit longer.
First of all, Unity does automatically create Instances, if I request a conecrete Type. This allows me to inject Types I register and Types, like Helper classes etc. I don't need to. This combination allows me to use DI everywhere.
Also in your Example I'd need to know the DataAcces in the WebGui, which is quite thight coupled. Well, I know there are solutions for this via Reflection, but I hoped Microsoft did something in this Topic, but probably that'd mean to big of a change.
Also allows Unity to store Instances or Instructions how to create them, another huge feature, which is missing at the moment.
Probably I'm just to spoiled, what refined DI-Libraries do, probably they also do to much, but at the moment the Microsoft-Implementation is just a huge downgrade according to my Information.
MVC Core follows the the composition root pattern, which is where object graphs are created based off of a set of instructions to instantiate them. I think you are misinterpreting what the IServiceCollection is for. It does not store instances, it stores instructions on how to create instances. The instances aren't actually created until a constructor somewhere in the object graph requests one as a constructor parameter.
So, in short the reason why your service (which you call UserEndPointAccess) is not being instantiated when you request it is because you have not configured the IServiceCollection with instructions on how to create it.
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.Configure<Model.Meta.AppSettings>(Configuration.GetSection("AppSettings"));
services.AddSingleton(typeof(Logic.UserEndPointConfigurationHandler));
services.AddSingleton(typeof(Logic.NetworkHandler));
// Need a way to instantiate UserEndPointAccess via DI.
services.AddSingleton(typeof(DataAccess.UserEndPointAccess));
services.AddMvc();
}
So it seems like even I directly request to DI an Class with a Parameterless-Constructor, I need to register that.
If you are doing DI correctly, each service class will only have a single constructor. If you have more than one it is known as the bastard injection anti-pattern, which essentially means you are tightly coupling your class definition to other classes by adding references to them as foreign defaults.
And yes, you need to register every type you require (that is not part of MVC's default registration). It is like that in Unity as well.

Using embedded WebResources throughout Webresource.axd

The question's simple: how could one use embedded resources in asp.net applications? What are the steps to include a resource in the assembly, and how to reference it? What are the gotchas that could be encountered?
Edit: For a version without referencing Page and ClientScript, see What is the right way to handle Embedded Resources on a Razor View?
After spending a half of a day I've learned these:
to embed a resource one needs to set it's Build Action to Embedded Resource (in VS Solution Explorer rightclick the file -> Properties)
next AsssemblyInfo.vb must be modified to make this resources available for WebResource queries. Add [Assembly: System.Web.UI.WebResource("MyWebResourceProj.Test.css", "text/css")] to AssemblyInfo.vb located in MyProject folder of the project.
The name consists of root namespace/assembly name +'.'+filename. To be 100% sure of the name, use the following code snippet to look it up:
Dim resNames = Assembly.LoadFile("YourDll.dll").GetManifestResourceNames()
Note that the assembly's Root Namespace must be the same as the Assembly Name (this took me about 4 hours to realize. At least with .Net v4 that is the case)
If there are references inside the css ( <%=WebResource("NS.image.jpg")%> ) than pass PerformSubstitution:=true for that css's WebResource attribute.
Referencing the resource can be done with Page.ClientScript.GetWebResourceUrl(GetType(MyWebResourceProj.ConssumingPage), "MyWebResourceProj.Test.css")
Note that instead of GetType(Typename) one could use Me.GetType(), but again, that won't work if the class is inherited, so beware!
Resources:
Debugging ASP.NET 2.0 Web Resources: Decrypting the URL and Getting the Resource Name
Using embedded resources through WebResource.axd is a pain in the neck, as you can see from your own answer. You have to keep assemblyinfo.vb|cs in sync, and it always seems damn near impossible to get all the namespace & assembly names right in all the right places.
When you finally get it to work, your reward is an include script line that that looks like a core memory dump.
I suggest an alternative. Write yourself a very simple web handler (e.g. MyResourceLoader.ashx. Then add a method to your class that simply serves it's own embedded resources, in whatever way you think is meaningful. You can use reflection to get the classes, like WebResource does, or just hardcode whatever you need into your loader, if it's just for a specific purpose. A public method in your class might look like:
public static Stream GetResource(string resourceName) {
// get the resource from myself, which is easy and doesn't require
// anything in assemblyinfo, and return it as a stream. As a bonus,
// you can parse it dynamically or even return things that aren't
// just embedded, but generated completely in code!
}
Or if you decide to make something more general purpose, you can get all fancy and return more data using a class, e.g.
class ResourceInfo
{
public Stream Data;
public string MimeType;
public string FileName;
}
Now you have the ability to serve up your embedded resources any way you want, e.g.
<script language="javascript" src="/MyResourceLoader.ashx/MyControlScript.js">
I think MS made a mess of that WebResource business. Luckily its' pretty straightforward to do your own thing.

ActionScript Interfaces with custom namespaces

Is there any way to get interface to play along with custom namespace? Example follows.
IHeaderRenderer.as:
public interface IHeaderRenderer{
function set header(value:IHeader):void;
function get header():IHeader;
}
HeaderRenderer.as
import fi.test.internalNamespace;
public class HeaderRenderer implements IHeaderRenderer{
internalNamespace function set header(value:IHeader):void{
// do something
}
internalNamespace function get header():IHeader{
// do something
}
}
This gives you the basic compiler error:
1044: Interface method get header in namespace fi.gridutils.headerrenderers:IHeaderRenderer not implemented by class fi.gridutils.headerrenderers.implementation:HeaderRenderer.
Why is this needed, you might ask. I'm developing a component, where the header accessors should not be directly visible to the components end user (developer), but if the developer wants to create his own Renderer he should know that they are needed. This is because the parent component will use these accessors to give the custom renderer the data it needs to render the header correctly.
Now to my mind there seems to be only three choices:
1) use public access control. This has the setback that the end developer will see accessors, which should not be directly accessed by him. Plus they add unnecessary clutter as they appear in auto-complete.
2) do not use interface. This means the end user has pretty poor options of developing the component further.
3) use the interface, but omit the accessors that use internalNamespace. Now the end developer will not know that he should add also header accessors to his custom headerrenderer class, which ends up in Flash Player giving following error to the developer in runtime:
Cannot create property internalNamespace/::header on fi.gridutils.headerrenderers.implementation.HeaderRenderer.
Sorry for all the blabbing. Any cunning ideas how this kind of situation could be handled?
In ActionScript, the interface methods need to be public. What good is an interface, if you can't guarantee the component using it can access the relevant interface methods?
that said, you can use the exclude metadata to prevent properties from showing up in code hinting.
Something like this:
[Exclude(name="header", kind="property")]
More info

Is there any way to use XmlSiteMapProvider within WinForm/Console/VSTest application?

I wonder whether there is a workaround for using the standard XmlSiteMapProvider within a non asp.net application, like WinForm/Console or, in my case, VS Unit Test one.
The following code fails, because it cannot create a path to the .sitemap file inside a private GetConfigDocument method.
XmlSiteMapProvider provider = new XmlSiteMapProvider();
NameValueCollection providerAttributes = new NameValueCollection();
providerAttributes.Add("siteMapFile", "Web.sitemap");
provider.Initialize("XmlSiteMapReader", providerAttributes);
provider.BuildSiteMap();
I feel the right solution is to write another provider.
I do not see why not. It is just a provider that implements an interface. You may not need many of the features, but you can access the API for what it provides you. Your WinForms screens can simply use the Urls for identification so that you can determine your place in the hierarchy.
What you may have to do is create a custom implementation of the provider because it will use the HttpContext to get the Url of the current web request to identify current placement while you will need to get that value differently. That is what could be tricky because your WinForm application could be displaying multiple windows at time. If you know there is only one window showing at a time you could use a static value which is set prior to accessing the SiteMap API.
Now you have to question the value of using an API if you have to do all of the work. There may not be enough benefit to make it worthwhile.

Resources