Save data to ViewState - javascript

I can tried save some data to ViewState, but i get this Error:
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerServerErrorException: Error serializing value 'HeRMeSSAAS.BussinesProcess.BussinesServices.CandidateService' of type 'HeRMeSSAAS.BussinesProcess.BussinesServices.CandidateService.'
Code:
private IActionService ActionService
{
get
{
return ViewState["ActionService"] as IActionService;
}
set
{
ViewState["ActionService"] = value;
}
}
private void InitializeField(IActionService service)
{
ActionService = service;
}
How i can store value to ViewState?

s your HeRMeSSAAS.BussinesProcess.BussinesServices.CandidateService decorated with the Serializable attribute?
eg:
[Serializable]
public class CandidateService
{
}
if this is not a very simple class I would also recommend storing it in the Session rather than the ViewState as it will take longer for the page to download and render

you need the [Serializable] Attribute on top of your business object.

Related

Set Image URL based on if condtion on ASPX page

As of now this code always works on my local and doesnt acts weird. But when we deploy on server even though if IsEnabled value is set to true it will load isfalse.gif and therafter few days it will start to load correct image based on IsEnabled value.
IsEnabled is an simple property defined in codebehind.
protected bool IsEnabled
{
get { return Utility.GetValue("TestKey"); }
}
Utility class pseudo:
public static class Utility
{
public static bool GetValue(string keyName)
{
bool kvalue = false;
// string value = string.Empty;
//the below cache is at global level defined below snippet is just pseudo how the data been present
Dictionary<string, string> dicCacheDictionary = new Dictionary<string, string>();
if (dicCacheDictionary.TryGetValue(keyName, out string value))
{
if (bool.TryParse(value, out bool result))
return result;
}
else
{
//GET FROM DATABASE AND add value to cache
//for now just for pseudo have hardcoded value
dicCacheDictionary.Add(keyName, "true");
}
//get from DB is not in cache
return kvalue;
}
}
ASPX Page :
<asp:Image ID="imgWebcast" ImageUrl='<%#(IsEnabled) ? "../../images/istrue.gif" : "../../images/isfalse.gif" %>' />
I looked at below areas and all looks good :
Cache precompiled files are deleted prior to deployment
Cached is cleared
IIS is reset
I can easily set it in code behind and resolve the above , but i need to understand the approach i did above is valid or not. Is something i am doing wrong. Does it achievable from the above approach

Is there a way to pass multiple (and different) parameters to an Apex Controller class from JS in Lightning Web Components (LWC)?

I'm currently stuck at a problem and was hoping someone here could help me. I also certainly hope this is the right place to ask it.
I'm trying to create a custom Invoice record with its corresponding Invoice Line records upon firing an event. I already have some logic in place to gather ID of selected rows in the JS.
I've gone so far as to be able to create the Invoice record (using LDS) and the Invoice Line records (using Apex), but can't seem to pass the Invoice ID for the Invoice Line records. I know I'm able to create the records because it works when I tested this with a hardcoded Invoice ID.
Would it be possible to pass multiple parameters of List and String to an Apex method in LWC?
I would appreciate any help. Thanks in advance!
JS
selectedRowsEvent(event) {
...some codes here...
this.selectedRecords = Array.from(conIds);
}
handleSave() {
**invId;**
...some codes here...
createRecord(recordInput)
.then(invoice => {
**this.invId = invoice.Id;**
**createInvLines({ lstConIds : this.selectedRecords, invoiceId : this.invId})**
}).catch(error => {
...some codes here...
});
}
Controller
#AuraEnabled
public static void createInvLines(list<Id> lstConIds, string invoiceId){
if(lstConIds.size() > 0){
List<OpportunityLine__c> oppLst = new List<OpportunityLine__c>([SELECT Id, Description__c FROM OpportunityLine__c WHERE Id = :lstConIds]);
try {
List<InvoiceLine__c> lstInvLinesToInsert = new List<InvoiceLine__c>();
for(OpportunityLine__c idCon : oppLst) {
lstInvLinesToInsert.add(new InvoiceLine__c(**InvoiceId__c = invoiceId**, Description__c = idCon.Description__c));
}
if(!lstInvLinesToInsert.isEmpty()) {
insert lstInvLinesToInsert;
}
}
catch(Exception ex) {
throw new AuraHandledException(ex.getMessage());
}
}
}
Yes, you can pass complex parameters to methods marked as #AuraEnabled. On client side it'll be a JSON object with right field names, like you already have { lstConIds : this.selectedRecords, invoiceId : this.invId}. On Apex side it can be a function with multiple arguments or just 1 argument (some helper wrapper class, again with right field names). Salesforce will "unpack" that JSON for you and put into right fields before your code is called.
Your preference which would be cleaner. I tend to use wrappers. If you have a reusable service-like function and you want to add some optional parameters later - you'd simply put new field in wrapper class and job done. Might be not as easy to add a new parameter to function used in other apex code, bit messier.
(in your scenario I'd definitely try to create invoice and line items as 1 call so if anything fails - the normal transaction rollback will help you. if one of items fails - you don't want to be left with just invoice header, right?)
Have you seen https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex ? it's a wall of text but it mentions interesting example, search for "apexImperativeMethodWithParams" in there.
Look at JS file here: https://github.com/trailheadapps/lwc-recipes/tree/master/force-app/main/default/lwc/apexImperativeMethodWithComplexParams
And see how it calls
ApexTypesController {
#AuraEnabled(cacheable=true)
public static String checkApexTypes(CustomWrapper wrapper) {
...
Where CustomWrapper is
public with sharing class CustomWrapper {
class InnerWrapper {
#AuraEnabled
public Integer someInnerInteger { get; set; }
#AuraEnabled
public String someInnerString { get; set; }
}
#AuraEnabled
public Integer someInteger { get; set; }
#AuraEnabled
public String someString { get; set; }
#AuraEnabled
public List<InnerWrapper> someList { get; set; }
}
The issue is that the inserts are asynchronous and you are firing them synchronously. So, that means you are trying to insert the lines before the parent record has completed.
// CREATE THE INVOICE RECORD
createRecord(recordInput)
.then(invoice => {
**this.invId = invoice.Id;**
// Call the next function here
// CREATE THE INVOICE LINE RECORDS
**createInvLines({ lstConIds : this.selectedRecords, invoiceId : this.invId})**
.then(result => {
...some codes here...
})
.catch(error => {
...some codes here...
});
);
}

Call Java method from JavaScript and return value to JavaScript

There are few SO questions and other articles about calling Java class method from Javascript but all of them deals with java method with return type void.
Here is what I am trying to achieve:
There are 2 strings to be displayed in WebView - say Yes and No. But they needs to be localized and hence I want to get the string value from Java method rather than using multiple JS for each locale.
Here's the code sample:
Java class
onCreate(){
//Some code
contentWebView.addJavascriptInterface(new CalculatorJavaScriptCallInterface(), "calculatorjavascriptcallinterface");
//Some code
}
String localizedString = "";
private class CalculatorJavaScriptCallInterface {
CalculatorJavaScriptCallInterface() {
}
#JavascriptInterface
public String getLocalizedString(final int stringId) {
localizedString = getResources().getString(stringId);
Toast.makeText(getActivity(), "localizedString :: " + localizedString, Toast.LENGTH_SHORT).show();
return localizedString;
}
}
Javascript file
function Checkboxpicker(element, options) {
//Some code
this.options = $.extend({}, $.fn.checkboxpicker.defaults, options, this.$element.data());
}
$.fn.checkboxpicker.defaults = {
//EXISTING STRINGS
//offLabel: 'No',
//onLabel: 'Yes',
offLabel: window.calculatorjavascriptcallinterface.getLocalizedString("Consult.JSSupport.checkbox.selected"),
onLabel: window.calculatorjavascriptcallinterface.getLocalizedString("Consult.JSSupport.checkbox.notSelected"),
};
I am getting blank string as output when I run above code.
Here are some notes:
This Javascript is being used appropriately as it works if I use
hard-coded strings
Respective stings have been defined in
string.xml
I tried using calculatorjavascriptcallinterface in
Camel case and lower case both
I tried with and without window.
to call Java method
Tried returning hard-coded value from Java
method - IT IS WORKING THIS WAY
Any suggestions will be appreciated. Thanks in advance!
EDIT
I'm getting following error even though the string is present in strings.xml:
No package identifier when getting value for resource number 0x00000000
android.content.res.Resources$NotFoundException: String resource ID #0x0
It looks like issue with getting the String with proper Id. change your getLocalizedString as follows:
#JavascriptInterface
public String getLocalizedString(final String stringId) {
localizedString = getResources().getString(getResources().getIdentifier(stringId,"string",getContext().getPackageNam‌​e()));
Toast.makeText(getActivity(), "localizedString :: " + localizedString, Toast.LENGTH_SHORT).show();
return localizedString;
}
1.)
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.addJavascriptInterface(new WebViewInterface(this), "Android");
mWebView.loadUrl("url or html file path");
2.)
public class WebViewInterface {
Context mContext;
WebViewInterface(Context mContext) {
this.mContext = mContext;
}
#JavascriptInterface
public void performAction(String pro_cat_id) {
//write your code here to perform any action.
}
3.)
<html>
<head>
<script type="text/javascript" src="/js/MyJS.js"></script>
</head>
<body>
<button onClick="mClick('1');">Yes</button>
<button onClick="mClick('0');">No</button>
</body>
</html>
4.) javascript: MyJS.js
function mClick(mValue)
{
Android.performAction(mId);
}

Breeze navigation properties

I have just started working with Breeze (using Angular) and have managed to get some data from my Odata service and displayed it on the page. However, I now need to get a related field via a foreign key (I need to get Group related to a Team object) and I am having some difficulties. Using datajs after version 1.0.3 causes issues so I am using version 1.0.3, but this version does not allow 'expand' to be used. So instead I have disabled lazy loading in my model and used Include when getting in my controller :
public partial class Team
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string FlagSmall { get; set; }
public string FlagLarge { get; set; }
public string BadgeSmall { get; set; }
public string BadgeLarge { get; set; }
public string TeamImage { get; set; }
//foreign key
public int GroupId { get; set; }
//navigation properties
public Group Group { get; set; } //virtual removed to disable lazy loading
}
// GET odata/Teams
[Queryable]
public IQueryable<Team> GetTeams()
{
return db.Teams.Include("Groups"); //get navigation property
}
// GET odata/Teams(5)
[Queryable]
public SingleResult<Team> GetTeam([FromODataUri] int key)
{
return SingleResult.Create(db.Teams.Include("Groups").Where(team => team.TeamId == key));
}
However, this does not work either, it gives a similar error to the error caused by > datajs 1.0.3 :
[Q] Unhandled rejection reasons (should be empty): ["createError#http://bras...s/datajs-1.0.3.js:1055\n"]
Has anybody got around this and managed to get related fields via a foreign key?
EDIT :
Here is my angular code, I have tried referring to team.Group.GroupName, team.GroupName, and group.GroupName, but neither of these works :
<tbody>
<tr ng-repeat="team in teams | filter:search:TeamName | orderBy:'TeamId'" id="team_{{team.id}}">
<td>{{team.TeamId}}</td>
<td>{{team.TeamName}}</td>
<td><img src={{team.FlagSmall}}></img></td>
<td><img style="width:40px;height:40px" src={{team.FlagLarge}}></img></td>
<td><img style="width:40px;height:40px" src={{team.BadgeSmall}}></img></td>
<td><img style="width:40px;height:40px" src={{team.BadgeLarge}}></img></td>
<td><img style="width:80px;height:40px" src={{team.TeamImage}}></img></td>
<td>{{team.Group.GroupName}}</td>
</tr>
</tbody>
EDIT 2 :
This is my Breeze query :
this.basicTeamQuery = function () {
return manager.executeQuery(entityQuery.from("Teams")).to$q();
};
EDIT 3 :
After some experimenting I managed to get this working with the following Breeze query :
this.basicTeamQuery = function () {
return manager.executeQuery(entityQuery.from("Teams").
select("TeamId, TeamName, FlagSmall, FlagLarge, BadgeSmall, BadgeLarge, TeamImage, " +
"Group.GroupName").expand("Group")).to$q();
};
Not sure if this is the correct way to do this, or even if it should work...isn't expand supposed to not work with Angular?
EDIT 4 :
Here is the final working query, no need for the select above :
this.basicTeamQuery = function () {
return manager.executeQuery(entityQuery.from("Teams").
expand("Group")).to$q();
};
I just tried it and it worked for me without any issue.
I see a typo in the snippet you copied in the question. Name of your navigation property defined in the Item class is Group, but you passed "Groups" to the Include function. Can you try it by fixing the typo and update if you still face the issue?
UPDATE:
It seems you cannot get the navigation property without using expand. Because, even the OData URL without expand doesn't send values of navigation properties despite of using Include in the LINQ query.
Try adding:
[ForeignKey("GroupId")]
[InverseProperty("Teams")]
public Group Group { get; set; }
EDIT:
After checking once again, I noticed that relationship is different than what I thought at first glance. Since one Group has MANY Teams, try query the other way:
[Queryable]
public IQueryable<Group> GetGroupsWithTeams()
{
return db.Groups.Include("Teams"); //get navigation property
}
That should return everything properly.

Suppress proxy generation for some hubs or methods

I'm starting out with SignalR and I have a situation where I'm going to have a SignalR site that will be broadcasting messages to clients, but I also need an admin interface that will actually trigger those messages. The admin page will call server side methods that will, in turn, call client side Javascript methods for regular users. So I'm thinking I can either set up two separate hubs (one for admin, one for everybody else) or I can have methods in a single hub that can only be called by the admin that will check authorization.
But in addition to the authorization, I'd like to have SignalR not include admin methods or an admin hub in the generated Javascript proxy classes so that I'm not advertising their existence (again - this is NOT the only security, I will be checking authorization). Is there an attribute or property I can set on individual hubs or on methods within a hub that will suppress them from being included in the proxy (but still have them callable from Javascript)? I know you can set EnableJavaScriptProxies to false in your HubConfiguration, but that seems to be global and I'd like to keep the proxy for the stuff I do want the regular client to be using.
There is one trick using interfaces. As proxy will generate only public methods in proxy, you can create hub using interface like this:
public class MyHub : Hub, IMyHub
{
void IMyHub.NotGeneratedOnClient()
{
}
public void GeneratedOnClient()
{
}
}
NotGeneratedOnClient method will not be visible if you use object of type MyHub, you can access it only using interface. As method is not public proxy generator is not going to add it to client proxy
We don't have a way of excluding specific methods from the proxy today. You'd have to re-implement your own proxy generator that basically does what we do in our default impl but has knowledge of some attribute to skip generation of specific methods.
We can conceivable add this in a future version of SignalR. File an issue on github if you feel strongly about having this.
Here's the default implementation (it would have been easier if we made more methods virtual and non static).
https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Core/Hubs/DefaultJavaScriptProxyGenerator.cs
Here is a modified DefaultJavaScriptProxyGenerator with the following changes:
It will exclude functions from Javascript proxy generation with a new [HubMethodExcludeFromProxy] attribute.
The private static functions have changed to protected virtual for future derivatives.
The GenerateProxy( ) function has an overload to include DocComments, but that was not caching the results like the non DocComments version. Now they both cache.
Two resources, Resources.DynamicComment_CallsMethodOnServerSideDeferredPromise and Resources.DynamicComment_ServerSideTypeIs were private to another assembly, so to get things to compile, I copied the text from the resource file directly. These two resources are only used if DocComments is true.
All of the DefaultJavaScriptProxyGenerator references were changed to CustomJavaScriptProxyGenerator except for one, which is used to locate the resource script Microsoft.AspNet.SignalR.Scripts.hubs.js, located in a different assembly.
First, you will need to update the dependency resolver to use the new CustomJavaScriptProxyGenerator for the IJavaScriptProxyGenerator interface. If you are using the default resolver, you can set up a custom resolver like this:
map.RunSignalR(
new HubConfiguration() {
Resolver = new CustomDependencyResolver()
}
);
And here is a custom resolver that derives from the DefaultDependecyResolver:
namespace Microsoft.AspNet.SignalR
{
public class CustomDependencyResolver : DefaultDependencyResolver
{
MyDependencyResolver() : base()
{
var proxyGenerator = new Lazy(() => new CustomJavaScriptProxyGenerator(this));
Register(typeof(IJavaScriptProxyGenerator), () => proxyGenerator.Value);
}
}
}
And finally, here is the new CustomJavaScriptProxyGenerator.cs file (the HubMethodExcludeFromProxyAttribute class is at the bottom):
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Mods by Brain2000
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNet.SignalR.Json;
using Microsoft.AspNet.SignalR.Hubs;
using Newtonsoft.Json;
namespace Microsoft.AspNet.SignalR.Hubs
{
public class CustomJavaScriptProxyGenerator : IJavaScriptProxyGenerator
{
protected static readonly Lazy _templateFromResource = new Lazy(GetTemplateFromResource);
protected static readonly Type[] _numberTypes = new[] { typeof(byte), typeof(short), typeof(int), typeof(long), typeof(float), typeof(decimal), typeof(double) };
protected static readonly Type[] _dateTypes = new[] { typeof(DateTime), typeof(DateTimeOffset) };
protected const string ScriptResource = "Microsoft.AspNet.SignalR.Scripts.hubs.js";
protected readonly IHubManager _manager;
protected readonly IJavaScriptMinifier _javaScriptMinifier;
protected readonly Lazy _generatedTemplate;
protected readonly Lazy _generatedTemplateWithComments;
public CustomJavaScriptProxyGenerator(IDependencyResolver resolver) :
this(resolver.Resolve(),
resolver.Resolve())
{
}
public CustomJavaScriptProxyGenerator(IHubManager manager, IJavaScriptMinifier javaScriptMinifier)
{
_manager = manager;
_javaScriptMinifier = javaScriptMinifier ?? NullJavaScriptMinifier.Instance;
_generatedTemplate = new Lazy(() => GenerateProxy(_manager, _javaScriptMinifier, includeDocComments: false));
_generatedTemplateWithComments = new Lazy(() => GenerateProxy(_manager, _javaScriptMinifier, includeDocComments: true));
}
public string GenerateProxy(string serviceUrl)
{
serviceUrl = JavaScriptEncode(serviceUrl);
return _generatedTemplate.Value.Replace("{serviceUrl}", serviceUrl);
}
public string GenerateProxy(string serviceUrl, bool includeDocComments)
{
if (!includeDocComments) return GenerateProxy(serviceUrl); //use the includeDocComments: false cached version
serviceUrl = JavaScriptEncode(serviceUrl);
return _generatedTemplateWithComments.Value.Replace("{serviceUrl}", serviceUrl);
}
protected virtual string GenerateProxy(IHubManager hubManager, IJavaScriptMinifier javaScriptMinifier, bool includeDocComments)
{
string script = _templateFromResource.Value;
var hubs = new StringBuilder();
var first = true;
foreach (var descriptor in hubManager.GetHubs().OrderBy(h => h.Name))
{
if (!first)
{
hubs.AppendLine(";");
hubs.AppendLine();
hubs.Append(" ");
}
GenerateType(hubManager, hubs, descriptor, includeDocComments);
first = false;
}
if (hubs.Length > 0)
{
hubs.Append(";");
}
script = script.Replace("/*hubs*/", hubs.ToString());
return javaScriptMinifier.Minify(script);
}
protected virtual void GenerateType(IHubManager hubManager, StringBuilder sb, HubDescriptor descriptor, bool includeDocComments)
{
// Get only actions with minimum number of parameters.
var methods = GetMethods(hubManager, descriptor);
var hubName = GetDescriptorName(descriptor);
sb.AppendFormat(" proxies['{0}'] = this.createHubProxy('{1}'); ", hubName, hubName).AppendLine();
sb.AppendFormat(" proxies['{0}'].client = {{ }};", hubName).AppendLine();
sb.AppendFormat(" proxies['{0}'].server = {{", hubName);
bool first = true;
foreach (var method in methods)
{
if (!first)
{
sb.Append(",").AppendLine();
}
GenerateMethod(sb, method, includeDocComments, hubName);
first = false;
}
sb.AppendLine();
sb.Append(" }");
}
protected virtual string GetDescriptorName(Descriptor descriptor)
{
if (descriptor == null)
{
throw new ArgumentNullException("descriptor");
}
string name = descriptor.Name;
// If the name was not specified then do not camel case
if (!descriptor.NameSpecified)
{
name = JsonUtility.CamelCase(name);
}
return name;
}
protected virtual IEnumerable GetMethods(IHubManager manager, HubDescriptor descriptor)
{
return from method in manager.GetHubMethods(descriptor.Name).Where(md => md.Attributes.FirstOrDefault(a => (a.GetType() == typeof(HubMethodExcludeFromProxyAttribute))) == null)
group method by method.Name into overloads
let oload = (from overload in overloads
orderby overload.Parameters.Count
select overload).FirstOrDefault()
orderby oload.Name
select oload;
}
protected virtual void GenerateMethod(StringBuilder sb, MethodDescriptor method, bool includeDocComments, string hubName)
{
var parameterNames = method.Parameters.Select(p => p.Name).ToList();
sb.AppendLine();
sb.AppendFormat(" {0}: function ({1}) {{", GetDescriptorName(method), Commas(parameterNames)).AppendLine();
if (includeDocComments)
{
sb.AppendFormat(" /// Calls the {0} method on the server-side {1} hub.\nReturns a jQuery.Deferred() promise.", method.Name, method.Hub.Name).AppendLine();
var parameterDoc = method.Parameters.Select(p => String.Format(CultureInfo.CurrentCulture, " /// Server side type is {2}", p.Name, MapToJavaScriptType(p.ParameterType), p.ParameterType)).ToList();
if (parameterDoc.Any())
{
sb.AppendLine(String.Join(Environment.NewLine, parameterDoc));
}
}
sb.AppendFormat(" return proxies['{0}'].invoke.apply(proxies['{0}'], $.merge([\"{1}\"], $.makeArray(arguments)));", hubName, method.Name).AppendLine();
sb.Append(" }");
}
protected virtual string MapToJavaScriptType(Type type)
{
if (!type.IsPrimitive && !(type == typeof(string)))
{
return "Object";
}
if (type == typeof(string))
{
return "String";
}
if (_numberTypes.Contains(type))
{
return "Number";
}
if (typeof(IEnumerable).IsAssignableFrom(type))
{
return "Array";
}
if (_dateTypes.Contains(type))
{
return "Date";
}
return String.Empty;
}
protected virtual string Commas(IEnumerable values)
{
return Commas(values, v => v);
}
protected virtual string Commas(IEnumerable values, Func selector)
{
return String.Join(", ", values.Select(selector));
}
protected static string GetTemplateFromResource()
{
//this must remain "DefaultJavaScriptProxyGenerator" because the resource "Microsoft.AspNet.SignalR.Scripts.hubs.js" lives there
using (Stream resourceStream = typeof(DefaultJavaScriptProxyGenerator).Assembly.GetManifestResourceStream(ScriptResource))
{
var reader = new StreamReader(resourceStream);
return reader.ReadToEnd();
}
}
protected virtual string JavaScriptEncode(string value)
{
value = JsonConvert.SerializeObject(value);
// Remove the quotes
return value.Substring(1, value.Length - 2);
}
}
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class HubMethodExcludeFromProxyAttribute : Attribute
{
}
}
Now all you need to do is all a decorator to your hub methods, such as:
public class MyHub : Hub
{
[HubMethodExcludeFromProxy]
public void NotGeneratedOnClient()
{
}
public void GeneratedOnClient()
{
}
}
EDIT : There is an issue with dependency injection where if you have two different instances of a resolver, one in the GlobalHost.DependencyResolver and one in the Signalr configuration, it will cause remote methods to sometimes not work. Here is the fix:
//use only !ONE! instance of the resolver, or remote SignalR functions may not run!
var resolver = new CustomDependencyResolver();
GlobalHost.Configuration.DependencyResolver = resolver;
map.RunSignalR(
new HubConfiguration() {
Resolver = resolver;
}
);
Reference: https://github.com/SignalR/SignalR/issues/2807

Categories

Resources