i often get argument mismatch error ,that usually take me a lot of time to debug program.damn, i really hope i know the function's entrance requirement and where they are come from.
since i only know a function variable is a function,no any other information.
i wrote massive codes like this
public static function call(func:Function,params:Array = null,addToTailIfNotNull:*=null):void{
if (func!=null){
var args:Array =[];
if(params!=null){
args = ArrayTools.clone(params);
}
if (addToTailIfNotNull!=null){
args.push(addToTailIfNotNull);
}
func.apply(null,args);
}
}
i should do things more smartly .
I can suggest you using flash.utils.describeType() method. It returns an XML with a description of an object you passed as a parameter.
Lets say you have a Class:
public class Example {
public function someMethod(number:Number, string:String):void {
}
}
And you call somewhere:
flash.utils.describeType(Example);
You should get an XML with something like this in there:
<method name="someMethod" declaredBy="com.example::Example" returnType="void">
<parameter index="1" type="Number" optional="false"/>
<parameter index="2" type="String" optional="false"/>
<metadata name="__go_to_definition_help">
<arg key="pos" value="501"/>
</metadata>
</method>
I am not sure that this is what you looking for, as in your example if you pass you Function argument there you will get a description of Function class:
<type name="builtin.as$0::MethodClosure" base="Function" isDynamic="false" isFinal="true" isStatic="false">
<extendsClass type="Function"/>
<extendsClass type="Object"/>
<accessor name="length" access="readonly" type="int" declaredBy="Function"/>
<accessor name="prototype" access="readwrite" type="*" declaredBy="builtin.as$0::MethodClosure"/>
</type>
But maybe you can refactor you "call" method so it could get the right description (for example pass additional info into it - like an object class and a method name - so you could analyse the method signature in it. Not the most beautiful solution, but still...)
Related
I have two behaviors configured in my endpoint:
One is for json serialization which is basically very similar to the exmaple here.
What's important there is the following:
public class NewtonsoftJsonBehaviorExtension : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(NewtonsoftJsonBehavior); }
}
protected override object CreateBehavior()
{
return new NewtonsoftJsonBehavior();
}
}
public class NewtonsoftJsonContentTypeMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Raw;
}
}
The other is for error handling. So that when exception is thrown a json formatted message will be sent to the client. The code is taken from here (The answer staring with: "Here's a complete solution based on some info from above:").
when I use only behavior 1 everything works fine. When I add the second behavior I get the following exception:
{"ExceptionType":"System.InvalidOperationException","Message":"The
incoming message has an unexpected message format 'Raw'. The expected
message formats for the operation are 'Xml', 'Json'. This can be
because a WebContentTypeMapper has not been configured on the binding.
See the documentation of WebContentTypeMapper for more details."}
Here is how my web.config looks like:
<services>
<service name="Algotec.Services.Archive.Data.ArchiveDataService" behaviorConfiguration="defaultBehavior">
<endpoint name="soap" address="soap" binding="basicHttpBinding" contract="Algotec.Interfaces.Archive.Data.IArchiveData" bindingNamespace="http://algotec.co.il/ArchiveData"/>
<endpoint name="restXml" address="" binding="webHttpBinding" contract="Algotec.Interfaces.Archive.Data.IArchiveData" behaviorConfiguration="restBehavior" bindingNamespace="http://algotec.co.il/ArchiveData"/>
<endpoint name="restJson" address="json" binding="webHttpBinding" contract="Algotec.Interfaces.Archive.Data.IArchiveData" behaviorConfiguration="jsonBehavior" bindingConfiguration="jsonBinding" bindingNamespace="http://algotec.co.il/ArchiveData"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
</service>
</services>
...
<endpointBehaviors>
<behavior name="restBehavior">
<enhancedWebHttp defaultOutgoingRequestFormat="Xml" defaultOutgoingResponseFormat="Xml"/>
</behavior>
<behavior name="jsonBehavior">
<enhancedWebHttp defaultOutgoingRequestFormat="Json" defaultOutgoingResponseFormat="Json" helpEnabled="true"/>
<newtonsoftJsonBehavior/>
<jsonErrorBehavior/>
</behavior>
</endpointBehaviors>
...
<extensions>
<behaviorExtensions>
<add name="newtonsoftJsonBehavior" type="Algotec.Services.Infra.BehaviorExtensions.NewtonsoftJsonBehaviorExtension, Algotec.Services.Infra, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
<add name="jsonErrorBehavior" type="Algotec.Services.Infra.Behaviors.JsonErrorWebHttpBehaviorElement, Algotec.Services.Infra, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
Any ideas?
Why are you returning WebContentFormat.Raw from NewtonsoftJsonContentTypeMapper? Shouldn't you be returning WebContentFormat.Json so that the format matches correctly?
Can you clarify a bit what you're trying to accomplish?
Here is what solved my problem:
In the web.config I simply switched the order between <newtonsoftJsonBehavior/> and <jsonErrorBehavior/>.
I admit that I don't understand completely all this behaviors and don't know why it helped but it did.
I'm using a ODataController to return data to the breeze dataservice, this is the dataservice
app.dataservice = (function (breeze) {
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager('/api/v1/');
return {
getRecipePage: getRecipePage
};
function getRecipePage(skip, take, searchText) {
var query = breeze.EntityQuery
.from("Recipes")
.orderBy("Name")
.skip(skip).take(take)
.inlineCount(true);
if (searchText) {
query = query.where("Name", "contains", searchText);
}
return manager.executeQuery(query);
}
})(breeze);
when calling the getRecipePage function in my controller, it seems to return data properly, but the exceptions is strange
getDataFunction(skip, take)
.then(function (largeLoad) {
$scope.setPagedData(largeLoad, currentPage, pageSize);
})
.fail(function (e) {
debugger;
});
The e variables has the message "; ", which makes no sense. The status is "200 OK" which is good.
The body contains my two entities and the url appers correct "/api/v1/Recipes?$orderby=Name&$top=2&$inlinecount=allpages", if I navigate to it, the json looks good:
{
"$id": "1",
"$type": "Breeze.WebApi2.QueryResult, Breeze.WebApi2",
"Results": [
{
"$id": "2",
"$type": "RecipeBook.Web.Angular.Models.RecipeBook.Recipe, RecipeBook.Web.Angular",
"Name": "1 Boiled Water",
"Description": "6 Steamy goodness!",
"Id": 1
},
{
"$id": "3",
"$type": "RecipeBook.Web.Angular.Models.RecipeBook.Recipe, RecipeBook.Web.Angular",
"Name": "2 Hot Chocolate",
"Description": "5 Chocolatey Chocolateness!",
"Id": 2
}
],
"InlineCount": 6
}
...what is this error? Lastly, here is the stack:
Error
at createError (http://localhost:62576/Scripts/breeze.debug.js:15182:22)
at http://localhost:62576/Scripts/breeze.debug.js:14971:40
at http://localhost:62576/Scripts/datajs-1.1.1.js:1671:17
at XMLHttpRequest.odata.defaultHttpClient.request.xhr.onreadystatechange (http://localhost:62576/Scripts/datajs-1.1.1.js:2587:25)
Thoughts as to what is going on???
EDIT:
After a ton of digging, I've somewhat narrowed down the issue to be related to the handler that reads the response. In datajs-1.1.1.js ~line 8100 there is a dispatchHandler function. I have a requestOrResponse that came back from the OData call:
It has a body property with the above json text. The data property is undefined however, but I think that's what it's trying to translate the body into...and is looking for a handler to do so. It's statusCode is 200, and statusText is OK. But the method doesn't find an appropriate handler and throws:
throw { message: "no handler for data" };
...this appears to be where the error originates. I just have no clue what's not setup correctly so that I can remedy the situation.
EDIT2:
It might actually be caused because the metadata (xml) isn't being parsed correctly..., this is what it looks like (taken from the datajs handlerRead function while debugging)
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<Schema Namespace="RecipeBook.Web.Angular.Models.Recipe" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="Recipe">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<Property Name="Description" Type="Edm.String" />
<Property Name="Steps" Type="Collection(Edm.String)" />
<NavigationProperty Name="Ingredients" Relationship="RecipeBook.Web.Angular.Models.Recipe.RecipeBook_Web_Angular_Models_Recipe_Recipe_Ingredients_RecipeBook_Web_Angular_Models_Recipe_RecipeIngredient_IngredientsPartner" ToRole="Ingredients" FromRole="IngredientsPartner" />
</EntityType>
<EntityType Name="RecipeIngredient">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="IngredientId" Type="Edm.Int32" Nullable="false" />
<Property Name="Quantity" Type="Edm.Int32" Nullable="false" />
<Property Name="UnitOfMeasureId" Type="Edm.Int32" Nullable="false" />
<Property Name="Notes" Type="Edm.String" />
</EntityType>
<Association Name="RecipeBook_Web_Angular_Models_Recipe_Recipe_Ingredients_RecipeBook_Web_Angular_Models_Recipe_RecipeIngredient_IngredientsPartner">
<End Type="RecipeBook.Web.Angular.Models.Recipe.RecipeIngredient" Role="Ingredients" Multiplicity="*" />
<End Type="RecipeBook.Web.Angular.Models.Recipe.Recipe" Role="IngredientsPartner" Multiplicity="0..1" />
</Association>
<EntityContainer Name="Container" m:IsDefaultEntityContainer="true">
<EntitySet Name="Recipes" EntityType="RecipeBook.Web.Angular.Models.Recipe.Recipe" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
EDIT3:
...so, if I use OData, as my dataService I need json metadata found at $metadata. If I use WebAPI it looks for metadata at /Metadata, and this can be Edmx or json. However, my metadata is returned as Edmx at $metadata ... which is the one thing not supported?
http://www.breezejs.com/documentation/breeze-metadata-details
I'm about to throw all this out (angular, breeze, odata) and just do it the old way.
Edit4:
This isn't a fix, but if I turn off metadata it "works"...so my issue is definitely related to Metadata not loading properly.
var dataService = new breeze.DataService({
serviceName: "/api/v1/",
hasServerMetadata: false
});
It looks like you are using Web API. Consider that you could decorate your controllers with the [BreezeController] attribute and instead of specifying OData you could use webApi which extends the configuration a bit. It's worth trying.
Also you probably need to configure the Breeze adapter to use backingStore which pairs well with Angular. - http://www.breezejs.com/samples/todo-dataservice (this link has some helpful tips to guide you through setting up Breeze to work well with Angular)
Last, remember that setting up any library the first time you use it always seems more difficult than it really is. Once you get it configured you almost never touch configuration again and instead Breeze just works and is really awesome.
EDIT
Check this link which has a brief walk-thru on Breeze, Angular, OData, and Web API - http://sravi-kiran.blogspot.com/2013/11/UsingBreezeJsToConsumeAspNetWebApiODataInAnAngularJsApplication.html
Another good 'How do I...' answer here by Ward -
How to consume OData service with Html/Javascript?
In another class elsewhere in the code, I want to access the parameters (and their types) of Foo.bar.
The result would contain [ "a", Number ] and [ "b", String ] in one form or another.
public class Foo
{
...
public function bar(a:Number, b:String):void
{
...
}
}
AS3 has a method called describeType
If you call describeType(Foo) on the above example, you'll get:
<type name="Foo" base="Class" isDynamic="true" isFinal="true" isStatic="true">
<extendsClass type="Class"/>
<extendsClass type="Object"/>
<accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
<factory type="Foo">
<extendsClass type="Object"/>
<method name="bar" declaredBy="Foo" returnType="void">
<parameter index="1" type="Number" optional="false"/>
<parameter index="2" type="String" optional="false"/>
<metadata name="__go_to_definition_help">
<arg key="pos" value="51"/>
</metadata>
</method>
<metadata name="__go_to_definition_help">
<arg key="pos" value="23"/>
</metadata>
</factory>
</type>
Now, you can use AS3's XML class and e4x to find the definition of the method with the name bar and grab the parameter elements.
I want to use the following load() method that accepts five parameters so that I can load a small "excerpt" from a larger video:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/fl/video/VideoPlayer.html#load()
In particular, the startTime and duration parameters seem to be what I need, but I am getting errors that seem to indicate that I don't have the right object/version of something, even though the Adobe docs say that it should work. Here are my steps:
Start a new, blank FLA document (AS3).
Drag an FLVPlayback component to the stage and name it vPlayer.
Create a new layer and add Actionscript in frame 1:
import fl.video.*;
var innerPlayer = vPlayer.getVideoPlayer(vPlayer.activeVideoPlayerIndex);
trace(innerPlayer); // "[object VideoPlayer]" appears in Output window
innerPlayer.load(
"RTMP://..."
, 0 // totalTime
, false // isLive
, 60 // startTime
, 10 // duration
);
This should give me a ten-second clip starting from the one-minute mark, but I keep getting errors like ArgumentError: Error #1063: Argument count mismatch on fl.video::VideoPlayer/load(). Expected 1, got 5.
I've also tried casting innerPlayer to fl.video.VideoPlayer, but that doesn't work.
What am I doing wrong?
EDITS: Even though I'm on CS4/AS3 and the documentation claims to apply to CS4/AS3, the class files in my "Component Source" folder don't seem to match the documentation. I also tried this in CS6, and I got "1137: Incorrect number of arguments. Expected no more than 3."
#SunilD. - For CS4: FLVPlayback.VERSION=2.1.0.19, and I am targeting Flash Player 10 (the most recent available)+AS3. For CS6, FLVPlayback.VERSION=2.5.0.26, and I am targeting Flash Player 11.4.
In CS4 and CS6, the errors say that VideoPlayer load() only requires one argument (with two optional), and play() has three optional arguments. The output of describeType(innerPlayer) confirms:
<type name="fl.video::VideoPlayer" base="flash.media::Video" isDynamic="false" isFinal="false" isStatic="false">
...
<method name="play" declaredBy="fl.video::VideoPlayer" returnType="void">
<parameter index="1" type="String" optional="true"/>
<parameter index="2" type="Number" optional="true"/>
<parameter index="3" type="Boolean" optional="true"/>
</method>
...
<method name="load" declaredBy="fl.video::VideoPlayer" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Number" optional="true"/>
<parameter index="3" type="Boolean" optional="true"/>
</method>
...
</type>
Other notes: Flash CS6 is up to date. Manually installing the FLVPlayback 2.5 component didn't work.
Anon, I think this is an issue of poor documentation / too many different products (Flash, Flex, player, flvplayback component) with different versions.
I was able to get the .load() call to work with all 5 arguments (and verified that it did start playing at the specified start time), but only by compiling a new FLVPlayback_116.swc from the latest Flex SDK source code (Flex 4.6 with playerglobal.swc version 11.6).
See my screenshot.
Might as well see if it works for you. Here's what you'll need to do:
Remove the FLVPlayback component from your library - this defines conflicting classes with the updated version.
Download my FLVPlayback_116.swc library
Or FLVPlayback_116_air.swc if you're targeting Adobe AIR, not Flash Player / web
In Flash, open the File -> ActionScript Settings dialog, under the library path tab, click 'Browse to SWC file' and locate the FLVPlayback_116.swc file you just downloaded. My screenshot above shows this dialog and how the FLVPlayback_116.swc file is listed after being added.
In the code (see below):
You need to set: fl.video.VideoPlayer.iNCManagerClass = fl.video.NCManager;
Rather than using innerPlayer = vPlayer.getVideoPlayer you'll need to use innerPlayer = new VideoPlayer(width,height) and then addChild(innerPlayer) and innerPlayer.play()
I had to add the innerVideo.play() call to start the video playing (which I assume the GUI would handle)
Here's my code (also visible in the screenshot):
import fl.video.*;
fl.video.VideoPlayer.iNCManagerClass = fl.video.NCManager;
var innerPlayer = new VideoPlayer(640,480);
addChild(innerPlayer);
innerPlayer.load(
"http://10.0.1.3/test.flv"
, 0 // totalTime
, false // isLive
, 5 // startTime
, 5 // duration
);
innerPlayer.play();
Also, you can see that my describeType of VideoPlayer shows the proper number of arguments:
<method name="load" declaredBy="fl.video::VideoPlayer" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Number" optional="true"/>
<parameter index="3" type="Boolean" optional="true"/>
<parameter index="4" type="Number" optional="true"/>
<parameter index="5" type="Number" optional="true"/>
<metadata name="__go_to_definition_help">
<arg key="pos" value="41308"/>
</metadata>
</method>
<method name="play" declaredBy="fl.video::VideoPlayer" returnType="void">
<parameter index="1" type="String" optional="true"/>
<parameter index="2" type="Number" optional="true"/>
<parameter index="3" type="Boolean" optional="true"/>
<parameter index="4" type="Number" optional="true"/>
<parameter index="5" type="Number" optional="true"/>
<metadata name="__go_to_definition_help">
<arg key="pos" value="34410"/>
</metadata>
</method>
UPDATE: I've updated the library so that you can instantiate an FLVPlayback(w,h) and hence apply skins or whatnot -- treat it just like you would the vPlayer in your code above (except I added the width/height constructor args, since the size used to come from the component on-stage). Instantiate it like so:
var vPlayer:FLVPlayback = new FLVPlayback(640,480);
vPlayer.skin = "http://10.0.1.3/skin.swf"; // optional skin
addChild(vPlayer);
var innerPlayer = vPlayer.getVideoPlayer(vPlayer.activeVideoPlayerIndex);
innerPlayer.load(
"http://10.0.1.3/test.flv"
, 0 // totalTime
, false // isLive
, 5 // startTime
, 5 // duration
);
Note - to use a skin, I compiled one of the FLA examples from Flash CS6... I tried using a skin I found on the Internet and it didn't work - it was likely compiled for an older version. See this skinned screenshot and download my skin.swf.
Good luck, and let me know if you need further info!
I am currently being confused by the Vector class.
I wrote a beautiful XML to TypedClass parser. Works beautifully and without fault. UNTIL a co-worker noticed we got a Conversion Error for Vector.<Number> to Vector.<*>.
Every Vector I've ever tested all extend Vector.<*>.
Vector.<Sprite>, Vector.<String>, Vector.<Point>, Vector.<Boolean>, Vector.<TextField>, Vector.<CustomObject>, etc etc etc. ALL of them.
<type name="__AS3__.vec::Vector.<String>" base="__AS3__.vec::Vector.<*>" isDynamic="true" isFinal="false" isStatic="false">
<extendsClass type="__AS3__.vec::Vector.<*>"/>
<extendsClass type="Object"/>
<accessor name="length" access="readwrite" type="uint" declaredBy="__AS3__.vec::Vector.<*>"/>
<accessor name="fixed" access="readwrite" type="Boolean" declaredBy="__AS3__.vec::Vector.<*>"/>
</type>
But then when I use describeType on Vector.<Number>, Vector.<uint> and Vector.<int>.
<type name="__AS3__.vec::Vector.<Number>" base="Object" isDynamic="true" isFinal="true" isStatic="false">
<extendsClass type="Object"/>
<constructor>
<parameter index="1" type="uint" optional="true"/>
<parameter index="2" type="Boolean" optional="true"/>
</constructor>
<accessor name="length" access="readwrite" type="uint" declaredBy="__AS3__.vec::Vector.<Number>"/>
<accessor name="fixed" access="readwrite" type="Boolean" declaredBy="__AS3__.vec::Vector.<Number>"/>
</type>
Now I have accounted for these 3 vectors individually as even uint and int does not extend Vector.<Number> as I would have expected.
And my parsing function works for all types correctly again. But my confusion comes as to WHY this is the case, and why I couldn't find any documentation on the subject.
I asked the same question on the Kirupa forums a few months back, but I cannot for the life of me find the thread.
If I remember this correctly, the Vector.<Number>, Vector.<int>, and Vector.<uint> (but not Boolean or String, oddly enough) classes are made to be as fast as possible, so they are written and treated as separate classes by the Flash Player.
As you have noticed, all other Vector classes extend Vector.<*> and type checking is done a bit differently (which is why Vectors are faster with int, uint, and Number, but Arrays are slightly faster for all other classes)
Anyway, that was the WHY. As for how to get around this issue, I'm afraid you are going to have to pass your vector as untyped to the function you want to use it in:
public function addItem(vector:*, item:*)
{ vector.push(item); }