I'm working on a Vue.JS project and I'm facing a strange error.
I got a WidgetDTO object filled by an axios.get request, it contains a WidgetParametersDTO object and it's defined like so:
export class WidgetParametersDTO {
[...]
public coverage: number = 0;
public colorOK: string = "";
public colorKO: string = "";
public constructor(parameters: any) {
this.coverage = parameters.coverage
this.colorOK = parameters.colorOK;
this.colorKO = parameters.colorKO;
}
}
export class WidgetDTO {
[...]
public id: string = null!;
public parameters: WidgetParametersDTO = null!;
public constructor(widgetDTO: any) {
this.id = widgetDTO.id;
this.parameters = new WidgetParametersDTO(widgetDTO.parameters);
}
When I print the full object widget.parameters, all attributes are correct, when I use widget.parameters.colorOK or widget.parameters.colorKO it works properly, but if I try to use widget.parameters.coverage, it shows 0 instead of the value printed earlier.
The type is correct (number) and I already tried several things to ensure the presence and correctness of the data, it's only acting like that when I use the attribute directly.
There's even more, I'm using npm run dev to be able to hot reload the changes as things progress. When I change some code and save, it reloads the page and prints the right value, but not when I'm hitting F5.
I tried to build the files and run the server with npm start but it didn't work.
Any advice ?
Thanks.
Related
I'm a bit lost trying to attach a pdf with populated values from an opportunity record
Here is the code:
Trigger:
trigger OpportunityTrigger on Opportunity (after insert)
if(trigger.isAfter && trigger.isUpdate) {
opportunityTriggerHelper.attachFileToOpportunityRecord(trigger.new);
}
Helper Class:
private void attachFileToOpportunityRecord(List<Opportunity> lstOpp) {
List<Id> oppListIdsForAttach = new List<Id>();
for(Opportunity opp : lstOpp) {
oppListIdsForAttach .add(opp.Id);
}
attachFileToOpportunities(oppListIdsForAttach);
}
#future(callout=true)
private static void attachFileToOppotunities(List<Id> OpportunityIds) {
List<Attachment> attachList = new List<Attachment>();
for(Id oppId : opportunityIds) {
OpportunityPdfController file = new OpportunityPdfController();
file.getData(oppId);
PageReference pdfPage = Page.PdfAttachmentForOpp;
blob pdfBody;
pdfBody = pdfPage.getContent();
Attachment attach = new Attachment();
attach.Body = pdfBody;
attach.Name = 'Pdf file';
attach.IsPrivate = false;
attach.ParenId = oppId;
attachList.add(attach);
}
insert attachList;
}
VF Page:
<apex:page controller="OpportunityPdfController" renderAs="pdf">
<apex:repeat value="{!pricingDetails}" var="pd">
<apex:outputText>{!pd.basePrice}</apex:outputText>
</apex:repeat>
</apex:page>
VF Page Controller:
public with sharing class OpportunityPdfController {
public List<PricingDetailWrapper> pricingDetails {get;set;}
public void getData(Id opportunityId) {
List<Pricing_Detail__c> pdList = [
SELECT basePrice
FROM Pricing_Detail__c
WHERE OpportunityId =: opportunityId
];
for(Pricing_Detail__c pd : pdList) {
PricingDetailWrapper pdw = new PricingDetailWrapper();
pdw.basePrice = pd.basePrice;
pricingDetails.add(pdw);
}
}
public class PricingDetailWrapper {
public String basePrice {get;set;}
}
}
The result is whenever I update an opportunity it attaches the corresponding pdf file but it is blank and if I add for example the following to vf page body: "<h1> hello World!</h1>" this works and shows as expected, but this is not happening to what I required above.
You didn't really pass the opportunity id to the VF page. And I doubt this actually works at all? If you manually access the VF page as /apex/PdfAttachmentForOpp?id=006... does it render the content ok? I'm assuming it doesn't.
Fixing the page
You didn't specify constructor so SF generates one for you, fine. I think you need to add something like
public OpportunityPdfController(){
if(ApexPages.currentPage() != null){
Id oppId = ApexPages.currentPage().getParameters().get('id');
System.debug(oppId);
getData(oppId);
}
}
Add this, try to access the page passing valid opp id and see if it renders ok, if right stuff shows in debug log. /apex/PdfAttachmentForOpp?id=006...
(VF page constructors are bigger topic, this might be simpler with standardController + extension class)
Fixing the callout
VF page (especially accessed as callout) will not share memory with the OpportunityPdfController controller you've created in the code. New object of this class will be created to support the page and your file will be ignored. You might try to make-do with some static variable holding current opportunity's id but it feels bit yucky.
In normal execute anonymous try if this returns correct pdf:
PageReference pdfPage = Page.PdfAttachmentForOpp;
pdfPage.getParameters().put('id', '006...');
Blob pdfBody = pdfPage.getContent();
System.debug(pdfBody.toString());
If it works - use similar trick in the actual code, pass the id as url parameter.
Version Akka.NET v1.3.8
Version Akka.TestKit.NUnit3 v1.3.2
Version NUnit v3.10.1
Platform Windows 10
I have an actor of the following kind:
public class BranchUsersActor : ReceiveActor
{
public BranchUsersActor()
{
Receive<UserBeingOnline>((online) =>
{
var userActorName = $"user_{online.UserId}";
if (Context.Child(userActorName).Equals(ActorRefs.Nobody))
{
var user = Context.ActorOf(UserActor.Props(online.UserId, online.BranchId), userActorName);
user.Tell(online);
}
});
}
public static Props Props(LoggingTags tags)
{
return Akka.Actor.Props.Create(() => new BranchUsersActor(tags));
}
}
When testing this actor, I expect that I will have a child actor.
I'm writing the next test to check this situation (using the NUnit framework):
[Test]
public void Test()
{
var branchUserActor = Sys.ActorOf(BranchUsersActor.Props());
branchUserActor.Tell(UserBeingOnline.Create(userId, branchId));
var expectedChildActor = Sys.ActorSelection($"{actorPath}/user_{userId.AkkaPrepare()}")
.ResolveOne(TimeSpan.FromSeconds(1)).Result;
Assert.IsNotNull(expectedChildActor);
}
I expect that within a second I will receive the child actor on the specified path, but I get ActorNotFoundExpection.
If I'm doing something like this:
[Test]
public void Test()
{
var branchUserActor = Sys.ActorOf(BranchUsersActor.Props());
branchUserActor.Tell(UserBeingOnline.Create(userId, branchId));
Task.Delay(100).ContinueWith(_ =>
{
var expectedChildActor = Sys.ActorSelection($"{actorPath}/user_{userId.AkkaPrepare()}")`enter code here`
.ResolveOne(TimeSpan.FromSeconds(1)).Result;
}
Assert.IsNotNull(expectedChildActor);
}
This works fine, but 1 of 10 times the test falls, because I get an ActorNotFoundException.
But I wonder why the first option does not work the way I expect?
Am I doing something wrong?
Thanks in advance for the answer.
branchUserActor.Tell(UserBeingOnline.Create(userId, branchId));
var expectedChildActor = Sys.ActorSelection($"{actorPath}/user_{userId.AkkaPrepare()}")
.ResolveOne(TimeSpan.FromSeconds(1)).Result;
The problem here is that when you're telling UserBeingOnline, you're triggering an asynchronous action - a message has been send to branchUserActor, but it may not have been processed right away. In the meantime you're calling resolve one, which tells actor system to find a child of branchUserActor - a child, which is not yet there, since the parent didn't handle the message yet.
You can use AwaitAssert(() => Assert.IsNotNull(ResolveChild())) method to work with that.
I have an MVC 4 application that sends out multiple emails. For example, I have an email template for submitting an order, a template for cancelling an order, etc...
I have an Email Service with multiple methods. My controller calls the Send method which looks like this:
public virtual void Send(List<string> recipients, string subject, string template, object data)
{
...
string html = GetContent(template, data);
...
}
The Send method calls GetContent, which is the method causing the problem:
private string GetContent(string template, object data)
{
string path = Path.Combine(BaseTemplatePath, string.Format("{0}{1}", template, ".html.cshtml"));
string content = File.ReadAllText(path);
return Engine.Razor.RunCompile(content, "htmlTemplate", null, data);
}
I am receiving the error:
The same key was already used for another template!
In my GetContent method should I add a new parameter for the TemplateKey and use that variable instead of always using htmlTemplate? Then the new order email template could have newOrderKey and CancelOrderKey for the email template being used to cancel an order?
Explanation
This happens because you use the same template key ("htmlTemplate") for multiple different templates.
Note that the way you currently have implemented GetContent you will run into multiple problems:
Even if you use a unique key, for example the template variable, you will trigger the exception when the templates are edited on disk.
Performance: You are reading the template file every time even when the template is already cached.
Solution:
Implement the ITemplateManager interface to manage your templates:
public class MyTemplateManager : ITemplateManager
{
private readonly string baseTemplatePath;
public MyTemplateManager(string basePath) {
baseTemplatePath = basePath;
}
public ITemplateSource Resolve(ITemplateKey key)
{
string template = key.Name;
string path = Path.Combine(baseTemplatePath, string.Format("{0}{1}", template, ".html.cshtml"));
string content = File.ReadAllText(path);
return new LoadedTemplateSource(content, path);
}
public ITemplateKey GetKey(string name, ResolveType resolveType, ITemplateKey context)
{
return new NameOnlyTemplateKey(name, resolveType, context);
}
public void AddDynamic(ITemplateKey key, ITemplateSource source)
{
throw new NotImplementedException("dynamic templates are not supported!");
}
}
Setup on startup:
var config = new TemplateServiceConfiguration();
config.Debug = true;
config.TemplateManager = new MyTemplateManager(BaseTemplatePath);
Engine.Razor = RazorEngineService.Create(config);
And use it:
// You don't really need this method anymore.
private string GetContent(string template, object data)
{
return Engine.Razor.RunCompile(template, null, data);
}
RazorEngine will now fix all the problems mentioned above internally. Notice how it is perfectly fine to use the name of the template as key, if in your scenario the name is all you need to identify a template (otherwise you cannot use NameOnlyTemplateKey and need to provide your own implementation).
Hope this helps.
(Disclaimer: Contributor of RazorEngine)
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 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.)