I am consuming an API mehod and it returns response as of type Product and below is the response class structure.
Public class Product
{
public int Id;
public string Name;
public IList<Product> MasterProduct { get; set; }
}
The API result include the product attributes along with IList. Since this API cannot be consumed directly though our windows client we have a wrapper web API which consume this API, for this in the local API we have defined similar Product class. The issue I am facing is when trying to map the attibues of external API with local. Below is what I am trying to do.
response = Response.Result.Select(x => new Product
{
Id=x.Id,
Name=x.Name
MasterProduct = x.MasterProduct.Cast<MasterProduct>().ToList()//tried below
}).ToList();
but it fails with error as - Unable to cast object of type 'Api.Models.Product' to type 'App.DataContracts.Product'
The Masterproduct consist of hierarchal data .I am wondering if the approach I am taking is right or it has to be done through some method. Any suggestion or help would be appreciated.
Upon searching the web I came across some code where serpare method is being called to parse using Microsoft.Its.Data, but this was for single object where as in my case I have a List(Hierarchical).
Appreciate if someone can point to some linke/sampel to achive the same.
Trying serialization/deserialization would do. Below is the code
Perhaps trying serialization/deserialization would do.
if (response.Result != null)
{
var serializedResponse = JsonConvert.SerializeObject(Response.Result, Formatting.Indented);
response = JsonConvert.DeserializeObject<List<Product>>(serializedResponse);
}).ToList();
return response;
Related
I am trying to update my LMS to be TinCanAPI compliant and while I have been able to capture the statements for the beginning and the end of the Tetris Example game I have been unable to update the ActivityProfile calls to highscores as I am unsure as to what exactly is required to be returned.
I have the following WebAPI controller:
public class ActivitiesController : ApiController
{
private XAPIBiz xvm;
public ActivitiesController()
{
MetaLearning.Data.MetaLearningContext dbcontext = new MetaLearningContext(System.Configuration.ConfigurationManager.ConnectionStrings["MetaLearningContext"].ConnectionString);
xvm = new MetaLearning.Biz.XAPIBiz(dbcontext);
}
// GET api/activity/5
public string Get([FromUri]string profileId, [FromUri]string activityId)
{
return "[{actor:{name:John Paul}, score:9921, date:2014-04-07T14:42:46.492Z},{actor:{name:John Paul}, score:4000, date:2014-04-07T14:42:46.492Z}]";
//var test = profileId;
//var test2 = activityId;
//return "value";
}
.......
}
If I try to view the leaderboard when the course is hosted on Cloud.Scorm.Com then I am able to see the request to /activities/profile?profileId=highscores&activityId=http%3A%2F%2Ftincanapi.com%2FJsTetris_TCAPI
I get the response of
"[{actor:{name:John Paul}, score:9921, date:2014-04-07T14:42:46.492Z},{actor:{name:John Paul}, score:4000, date:2014-04-07T14:42:46.492Z}]"
But If I try to return just the string value of this for testing purposes I get a list of 137 undefined on the leaderboard.
If I return void in this controller action then the leaderboard appears blank.
If I save the text in this file as a json file and save to blob storage and then try to return a URI pointing to the file I get an undefined list of 66 names.
Any help in furthering my understanding of how the ActivityProfile API works would be greatly appreciated. What is the implementation on SCORM cloud?
I need to group some data from a SQL Server database and since LightSwitch doesn't support that out-of-the-box I use a Domain Service according to Eric Erhardt's guide.
However my table contains several foreign keys and of course I want the correct related data to be shown in the table (just doing like in the guide will only make the key values show). I solved this by adding a Relationship to my newly created Entity like this:
And my Domain Service class looks like this:
public class AzureDbTestReportData : DomainService
{
private CountryLawDataDataObjectContext context;
public CountryLawDataDataObjectContext Context
{
get
{
if (this.context == null)
{
EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
builder.Metadata =
"res://*/CountryLawDataData.csdl|res://*/CountryLawDataData.ssdl|res://*/CountryLawDataData.msl";
builder.Provider = "System.Data.SqlClient";
builder.ProviderConnectionString =
WebConfigurationManager.ConnectionStrings["CountryLawDataData"].ConnectionString;
this.context = new CountryLawDataDataObjectContext(builder.ConnectionString);
}
return this.context;
}
}
/// <summary>
/// Override the Count method in order for paging to work correctly
/// </summary>
protected override int Count<T>(IQueryable<T> query)
{
return query.Count();
}
[Query(IsDefault = true)]
public IQueryable<RuleEntryTest> GetRuleEntryTest()
{
return this.Context.RuleEntries
.Select(g =>
new RuleEntryTest()
{
Id = g.Id,
Country = g.Country,
BaseField = g.BaseField
});
}
}
public class RuleEntryTest
{
[Key]
public int Id { get; set; }
public string Country { get; set; }
public int BaseField { get; set; }
}
}
It works and all that, both the Country name and the Basefield loads with Autocomplete-boxes as it should, but it takes VERY long time. With two columns it takes 5-10 seconds to load one page.. and I have 10 more columns I haven't implemented yet.
The reason it takes so long time is because each related data (each Country and BaseField) requires one request. Loading a page looks like this in Fiddler:
This isn't acceptable at all, it should be a way of combining all those calls into one, just as it does when loading the same table without going through the Domain Service.
So.. that was a lot explaining, my question is: Is there any way I can make all related data load at once or improve the performance by any other way? It should not take 10+ seconds to load a screen.
Thanks for any help or input!s
My RIA Service queries are extremely fast, compared to not using them, even when I'm doing aggregation. It might be the fact that you're using "virtual relationships" (which you can tell by the dotted lines between the tables), that you've created using your RuleEntryTest entity.
Why is your original RuleEntry entity not related to both Country & BaseUnit in LightSwitch BEFORE you start creating your RIA entity?
I haven't used Fiddler to see what's happening, but I'd try creating "real" relationships, instead of "virtual" ones, & see if that helps your RIA entity's performance.
I think I could be using this wrong, there wasn't much on the Ninject variant of multiple cores, but I'm trying to use Ninject and SolrNet. While taking advantage of fully loose mapping. So I know I need to use Ninject named bindings. Can't use Windsor, it's dll's don't seem to play well with our current stuff.
Suspect code:
SolrServers cores = new SolrServers();
cores.Add(new SolrServerElement
{
Id = "index1",
DocumentType = typeof(ISolrOperations<Dictionary<string, object>>).AssemblyQualifiedName,
Url = "http://localhost:8080/solr/index1",
});
cores.Add(new SolrServerElement
{
Id = "index2",
DocumentType = typeof(ISolrOperations<Dictionary<string, object>>).AssemblyQualifiedName,
Url = "http://localhost:8080/solr/index2",
});
var kernal = new StandardKernel(new SolrNetModule(cores));
var operations = kernal.Get<ISolrOperations<Dictionary<string, object>>>("index1");
Error Produced:
Test 'Test.DifferentTest' failed:
Ninject.ActivationException : Error activating ISolrOperations{Dictionary{string, Object}}
No matching bindings are available, and the type is not self-bindable.
Activation path:
1) Request for ISolrOperations{Dictionary{string, Object}}
I understand the concept of DI, however I don't know much more than that because in MVC everything seemed hidden from me. So any additional explanation, on why this is dumb/how SolrNet interacts with it, would be appreciated.
Link to SolrNet Module https://github.com/mausch/SolrNet/blob/master/Ninject.Integration.SolrNet/SolrNetModule.cs
Since I see that you are using the fully loose mapping capabilities of SolrNet, you could implement the following dynamic mappings as a workaround until support for the same type/class is added to SolrNet for Ninject.
public class Index1Item
{
SolrField["*"]
public IDictionary<string, object> Fields { get; set; }
}
public class Index2Item
{
SolrField["*"]
public IDictionary<string, object> Fields { get; set; }
}
Please see Mappings on SolrNet project page for more details on this dynamic mapping.
Then your SolrNet setup would change to the following:
SolrServers cores = new SolrServers();
cores.Add(new SolrServerElement
{
Id = "index1",
DocumentType = typeof(Index1Item).AssemblyQualifiedName,
Url = "http://localhost:8080/solr/index1",
});
cores.Add(new SolrServerElement
{
Id = "index2",
DocumentType = typeof(Index2Item).AssemblyQualifiedName,
Url = "http://localhost:8080/solr/index2",
});
var kernal = new StandardKernel(new SolrNetModule(cores));
var operations = kernal.Get<ISolrOperations<Index1Item>>("index1");
Hopefully this will help...
I have not yet used Solr but from the Module I found on github I'd say you have to assign the generic type argument to the document type instead of ISolrOperations
SolrNet has since been updated to support multiple cores of the same DocumentType with named bindings so your suspect code should work now.
I doubt anyone has specific experience related to this particular task, but maybe you can spot my problem. I'm trying to make a call to lithium (forum software) to place a vote in their poll, and their docs show this:
Example URL:
http://community.lithium.com/community-name/restapi/vc/polls/id/15/votes/place
Query Arguments:
poll.choice (required): - the choice to place the vote for. The choice is specified by a string of the form id/choice_id where choice_id is the id of the poll choice
Http Method:
POST
So my code looks something like this:
Dim _Response As New XmlDocument
Dim RestApiRoot As String = "http://example.com/community-name/restapi/vc/polls/id/6/votes/place"
APIRequest = WebRequest.Create(RestApiRoot)
APIRequest.Method = "POST"
APIRequest.Headers.Add("poll.choice", HttpContext.Current.Server.UrlEncode("id/" & _choiceID.ToString))
APIResponse = APIRequest.GetResponse()
APIReader = New StreamReader(APIResponse.GetResponseStream())
_Response.LoadXml(APIReader.ReadToEnd())
APIResponse.Close()
I'm not able to successfully register a vote and they say it's because the poll.choice param is not appearing in the header, but if I step through debugging, I see it in the Header Keys/Items just fine.
Anyone have any clue what I might be doing wrong?
I do exactly this with RestSharp, an open source REST framework. It works great with the Lithium REST API.
You're code will look something like this using RestSharp:
You'll create a class to look like the response from the Lithium API, in this case "Response". It will look like this (sorry, you'll have to translate this to VB.NET):
public class LithiumResponse
{
public string status { get; set; }
public string value { get; set; }
public string message { get; set; }
}
Now RestSharp will use that to capture the result like this:
// create the request
var request = new RestRequest();
request.Verb = Method.POST;
request.BaseUrl = "http://example.com/community-name";
// specify the action
request.Action = "restapi/vc/polls/id/6/votes/place";
// add the parameters
request.AddParameter("poll.choice", "id/" + _choiceID.ToString());
// now create a RestClient to execute the request,
// telling it to put the results in your "reponse" class
var client = new RestClient();
var lithiumresponse = client.Execute<LithiumResponse>(request);
// now you can check the status property of your class to
// see if it was successful
if (lithiumresponse.status == "success")
// you successfully placed a vote
I use RestSharp for a lot of interaction with the Lithium API and it makes it brain-dead simple. Pretty awesome library.
I am having a minor problem with WCF service proxies where the message contains List<string> as a parameter.
I am using the 'Add Service reference' in Visual Studio to generate a reference to my service.
// portion of my web service message
public List<SubscribeInfo> Subscribe { get; set; }
public List<string> Unsubscribe { get; set; }
These are the generated properties on my MsgIn for one of my web methods.
You can see it used ArrayOfString when I am using List<string>, and the other takes List<SubscribeInfo> - which matches my original C# object above.
[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
public System.Collections.Generic.List<DataAccess.MailingListWSReference.SubscribeInfo> Subscribe {
get {
return this.SubscribeField;
}
set {
if ((object.ReferenceEquals(this.SubscribeField, value) != true)) {
this.SubscribeField = value;
this.RaisePropertyChanged("Subscribe");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
publicDataAccess.MailingListWSReference.ArrayOfString Unsubscribe {
get {
return this.UnsubscribeField;
}
set {
if ((object.ReferenceEquals(this.UnsubscribeField, value) != true)) {
this.UnsubscribeField = value;
this.RaisePropertyChanged("Unsubscribe");
}
}
}
The ArrayOfString class generated looks like this. This is a class generated in my code - its not a .NET class. It actually generated me a class that inherits from List, but didn't have the 'decency' to create me any constructors.
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.CollectionDataContractAttribute(Name="ArrayOfString", Namespace="http://www.example.com/", ItemName="string")]
[System.SerializableAttribute()]
public class ArrayOfString : System.Collections.Generic.List<string> {
}
The problem is that I often create my message like this :
client.UpdateMailingList(new UpdateMailingListMsgIn()
{
Email = model.Email,
Name = model.Name,
Source = Request.Url.ToString(),
Subscribe = subscribeTo.ToList(),
Unsubscribe = unsubscribeFrom.ToList()
});
I really like the clean look this gives me.
Now for the actual problem :
I cant assign a List<string> to the Unsubscribe property which is an ArrayOfString - even though it inherits from List. In fact I cant seem to find ANY way to assign it without extra statements.
I've tried the following :
new ArrayOfString(unsubscribeFrom.ToList()) - this constructor doesn't exist :-(
changing the type of the array used by the code generator - doesn't work - it always gives me ArrayOfString (!?)
try to cast List<string> to ArrayOfString - fails with 'unable to cast', even though it compiles just fine
create new ArrayOfString() and then AddRange(unsubscribeFrom.ToList()) - works, but I cant do it all in one statement
create a conversion function ToArrayOfString(List<string>), which works but isn't as clean as I want.
Its only doing this for string, which is annoying.
Am i missing something? Is there a way to tell it not to generate ArrayOfString - or some other trick to assign it ?
Any .NET object that implements a method named "Add" can be initialized just like arrays or dictionaries.
As ArrayOfString does implement an "Add" method, you can initialize it like this:
var a = new ArrayOfString { "string one", "string two" };
But, if you really want to initialize it based on another collection, you can write a extension method for that:
public static class U
{
public static T To<T>(this IEnumerable<string> strings)
where T : IList<string>, new()
{
var newList = new T();
foreach (var s in strings)
newList.Add(s);
return newList;
}
}
Usage:
client.UpdateMailingList(new UpdateMailingListMsgIn()
{
Email = model.Email,
Name = model.Name,
Source = Request.Url.ToString(),
Subscribe = subscribeTo.ToList(),
Unsubscribe = unsubscribeFrom.To<ArrayOfString>()
});
I prefer not to return generic types across a service boundary in the first place. Instead return Unsubscribe as a string[], and SubscriptionInfo as SubscriptionInfo[]. If necessary, an array can easily be converted to a generic list on the client, as follows:
Unsubscribe = new List<string>(unsubscribeFrom);
Subscribe = new List<SubscriptionInfo>(subscribeTo);
Too late but can help people in the future...
Use the svcutil and explicitly inform the command line util that you want the proxy class to be serialized by the XmlSerializer and not the DataContractSerializer (default). Here's the sample:
svcutil /out:c:\Path\Proxy.cs /config:c:\Path\Proxy.config /async /serializer:XmlSerializer /namespace:*,YourNamespace http://www.domain.com/service/serviceURL.asmx
Note that the web service is an ASP.NET web service ok?!
If you are using VS 2008 to consume service then there is an easy solution.
Click on the "Advanced..." button on the proxy dialog that is displayed when you add a Service Reference. In the Collection Type drop down you can select System.Generic.List. The methods returning List should now work properly.
(Hope this is what you were asking for, I'm a little tired and the question was a tad difficult for me to read.)