I am trying to resolve an issue on CFWheels, where I am have trouble extending my parent Application.cfc which also extends another Application.cfc. In order to understand the problem better and really single out what's going wrong, I have created a directory structure as follows:
/mainapp/index.cfm
-------------------------------------------------
<cfoutput>
<cfdump var="#session#">
</cfoutput>
/mainapp/Application.cfc
-------------------------------------------------
<cfscript>
component
{
this.name = "Main App";
this.applicationTimeout = createTimeSpan(0, 1, 0, 0);
this.sessionManagement = true;
this.sessionTimeout = createTimeSpan(0, 0, 30, 0);
public function intMainApp(name, value){
session[name] = value;
}
public boolean function OnApplicationStart(){
//Handle OnApplicationStart Callback
return true;
}
public void function OnApplicationEnd(struct ApplicationScope=structNew()){
//Handle OnApplicationEnd Callback
}
public void function OnRequest(required string TargetPage){
//Handle OnRequest Callback
}
public boolean function OnRequestStart(required string TargetPage){
//Handle OnRequestStart Callback
include arguments.TargetPage;
intMainApp("mainappv1", "something session");
return true;
}
public void function OnSessionStart(){
//Handle OnSessionStart Callback
}
public void function OnSessionEnd(required struct SessionScope, struct ApplicationScope=structNew()){
//Handle OnSessionEnd Callback
}
}
</cfscript>
/mainapp/submainapp/index.cfm
-------------------------------------------------
<cfoutput>
<cfdump var="#session#">
</cfoutput>
/mainapp/submainapp/Application.cfc
-------------------------------------------------
<cfscript>
component extends="mainapp.Application"
{
this.name = "Main App";
this.applicationTimeout = createTimeSpan(0, 1, 0, 0);
this.sessionManagement = true;
this.sessionTimeout = createTimeSpan(0, 0, 30, 0);
public function intSubMainApp(name, value){
session[name] = value;
}
public boolean function OnApplicationStart(){
//Handle OnApplicationStart Callback
return true;
}
public void function OnApplicationEnd(struct ApplicationScope=structNew()){
//Handle OnApplicationEnd Callback
}
public void function OnRequest(required string TargetPage){
//Handle OnRequest Callback
}
public boolean function OnRequestStart(required string TargetPage){
//Handle OnRequestStart Callback
include arguments.TargetPage;
intSubMainApp("submainapp2", "var var 2");
intMainApp("v3", "var 3");
return true;
}
public void function OnSessionStart(){
//Handle OnSessionStart Callback
}
public void function OnSessionEnd(required struct SessionScope, struct ApplicationScope=structNew()){
//Handle OnSessionEnd Callback
}
}
</cfscript>
/mainapp/submainapp/childapp/index.cfm
-------------------------------------------------
<cfoutput>
<p>Testing Child App</p>
</cfoutput>
/mainapp/submainapp/childapp/Application.cfc
-------------------------------------------------
<cfcomponent output="false">
<cfinclude template="../Application.cfc">
</cfcomponent>
If I execute the childapp/index.cfm I get the error.
Variable INTMAINAPP is undefined.
This problem is similar to the issue that I facing with cfwheels when trying to extend my parent Application.cfc. Why is it that InitMainApp method not being included in submainapp/Application.cfc when it used via cfinclude tag and Is there a workaround or fix for this problem.
Just as a clarification, childapp/Application.cfc is trying to include submainapp/Application.cfc
Moreover there is a issue created on this in the cfwheels community forums.
https://groups.google.com/forum/#!topic/cfwheels/1eMGLGSrbBY
Related
Hey I am trying to use livewire for the first time and I successfuly done the function and when its finish the function checkSingleLink() its shows this error :
"render" method on [App\Http\Livewire\SingleAsset] must return instance of [Illuminate\View\View]
the Livewire Model
namespace App\Http\Livewire;
use Illuminate\Http\Request;
use App\Models\Links;
use App\Models\Cron;
use Livewire\Component;
class SingleAsset extends Component
{
public $saved = False;
protected $fillable = [
'keyword', 'data', 'updated_at'
];
public function __construct() {
$this->cron = new Cron();
}
public function render(Request $request)
{
if(Links::where('asset_id', '=', $request->id)->exists()){
$links = Links::where('asset_id', '=', $request->id)->get();
return view('livewire.single-asset', compact('links'));
}
}
public function checkSingleLink(Links $link, $keyword) {
// cron::fetchUrl($link->link, $keyword);
$data = $this->cron->fetchUrl($link->link, $keyword);
$link->keyword = $keyword;
$link->data = $data;
$link->save();
// dd($this->cron->fetchUrl($link->link, $keyword));
session()->flash('message', "link checked");
$this->saved = TRUE;
}
}
this is the location where I call the function
<input class="inputs" style="border:0;" type="text" value="{{$link->keyword}}" wire:keydown.enter="checkSingleLink({{$link}}, $event.target.value)"/>
this part of the calling and making the function working but after when he need to render again the response its not working
I seem to be stuck at developing a custom Key/Value pair provider for Amazon's System Manager Parameter Store (SSM) using NETFramework 4.7.1 that utilizes Microsoft.Configuration.ConfigurationBuilders.
The implementation:
using System;
using System.Collections.Generic;
using Amazon.SimpleSystemsManagement;
using Amazon.SimpleSystemsManagement.Model;
using Microsoft.Configuration.ConfigurationBuilders;
using System.Linq;
using System.Diagnostics;
using System.Collections.Specialized;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
using System.Configuration;
using System.Threading.Tasks;
namespace AXS.Configurations
{
public class ParameterStoreConfigBuilder : KeyValueConfigBuilder
{
public const string envTag = "Environment";
public const string appNameTag = "AppName";
private IAmazonSimpleSystemsManagement client;
/// <summary>
/// Gets or sets an environment (dev|qa|staging|production)
/// </summary>
public string Environment { get; set; }
/// <summary>
/// Gets or sets a AppName
/// </summary>
public string AppName { get; set; }
public ParameterStoreConfigBuilder(IAmazonSimpleSystemsManagement client,
string appName,
string environment)
{
this.client = client;
Environment = environment.ToLower();
AppName = appName;
}
public ParameterStoreConfigBuilder()
{
client = new AmazonSimpleSystemsManagementClient();
}
public override string Description => "Parameter Store";
public override string Name => "SSM";
protected override void LazyInitialize(string name, NameValueCollection config)
{
Optional = false;
base.LazyInitialize(name, config);
string env = UpdateConfigSettingWithAppSettings(envTag);
if (string.IsNullOrWhiteSpace(env))
throw new ArgumentException($"environment must be specified with the '{envTag}' attribute.");
Environment = env;
string appName = UpdateConfigSettingWithAppSettings(appNameTag);
if (string.IsNullOrWhiteSpace(appName))
throw new ArgumentException($"appName must be specified with the '{appNameTag}' attribute.");
AppName = appName;
client = new AmazonSimpleSystemsManagementClient("","", Amazon.RegionEndpoint.USWest2);
}
public override ICollection<KeyValuePair<string, string>> GetAllValues(string prefix)
{
Trace.TraceInformation($"return values prefix {prefix}");
if (client == null)
return null;
var parameters = new List<Parameter>();
string nextToken = null;
do
{
var response = client.GetParametersByPath(new GetParametersByPathRequest { Path = prefix, Recursive = true, WithDecryption = true, NextToken = nextToken });
nextToken = response.NextToken;
parameters.AddRange(response.Parameters);
} while (!string.IsNullOrEmpty(nextToken));
return parameters.Select(p => new
{
Key = p.Name,
p.Value
}).ToDictionary(parameter => parameter.Key, parameter => parameter.Value, StringComparer.OrdinalIgnoreCase);
}
public override string GetValue(string key)
{
return Task.Run(async () => { return await GetValueAsync(key); }).Result;
}
private async Task<string> GetValueAsync(string key)
{
var name = $"/{Environment}/{AppName}/{key.Replace(':', '/')}";
Trace.WriteLine($"get value async:{name}");
if (client == null)
return null;
try
{
Trace.TraceInformation($"fetch key {name}");
var request = new GetParameterRequest
{
Name = name,
WithDecryption = true
};
var response = await client.GetParameterAsync(request);
var parameter = response.Parameter;
var value = parameter.Type == ParameterType.SecureString ? "*****" : parameter.Value;
Trace.TraceInformation($"fetched name={name} value={value}");
return value;
}
catch (Exception e) when (Optional && ((e.InnerException is System.Net.Http.HttpRequestException) || (e.InnerException is UnauthorizedAccessException))) { }
return null;
}
}
}
The problem seems to be that AWS SSM client never gets created.
If I change the code and try to instantiate in the constructor I get a stack overflow exception due to recursion.
Any ideas on how to force to get AmazonSimpleSystemsManagementClient created?
The code uses guidance from https://github.com/aspnet/MicrosoftConfigurationBuilders
The App.Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection,
System.Configuration, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
restartOnExternalChanges="false"
requirePermission="true" />
</configSections>
<configBuilders>
<builders>
<add name="ParameterStore" Environment="development" AppName="myAppNameforParmStore" type="AXS.Configurations.ParameterStoreConfigBuilder, AXS.Configurations" />
<add name="Env" prefix="appsettings_" stripPrefix="true" type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Environment, Version=2.0.0.0, Culture=neutral" />
</builders>
</configBuilders>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
<appSettings configBuilders="Env,ParameterStore">
<add key="Url" value="URL Value for from paramter Store" />
<add key="Secret" value="Some Secret value decrypted" />
</appSettings>
</configuration>
Thanks
UPDATE
I posted an updated version of the AwsSsmConfigurationBuilder, and a sample ASP.NET Web Forms project that uses it, on my GitHub:
https://github.com/Kirkaiya/AwsSsmConfigBuilderPoC/
Disclaimer: This is a proof-of-concept (POC) for a custom ConfigurationBuilder for ASP.NET 4.7.1 or higher (running on .NET Framework obviously). It's a POC, so it doesn't do anything besides allow you store Configuration AppSettings in AWS Parameter Store (a feature of Simple Systems Manager). So, clearly, don't use this in production without productizing and testing it!
Prerequisites:
Your project must target .NET Framework 4.7.1 or higher
Include NuGet package Microsoft.Configuration.ConfigurationBuilders.Base
Have parameters in AWS SSM Parameter Store that have the same name (not counting the prefix) as parameters in your web.config file, and vice-versa.
Notes
In order to avoid recursively calling a concrete constructor or Initialize, I used a static constructor to instantiate the AmazonSimpleSystemsManagementClient, which is held in a static member.
Web.Config additions
Note: change the assembly/class-name of your builder to match yours, etc.
<configSections>
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false" />
</configSections>
<configBuilders>
<builders>
<add name="ParameterStore" ssmPrefix="/padnugapp/ApiKeys" type="Microsoft.Configuration.ConfigurationBuilders.AwsSsmConfigBuilder, AspNetWebFormsSample" />
</builders>
</configBuilders>
<appSettings configBuilders="ParameterStore">
<add key="TestKey" value="TestKey Value from web.config" />
<add key="TwitterKey" value="TwitterKey value from web.config" />
</appSettings>
And the AwsSsmConfigBuilder.cs file:
namespace Microsoft.Configuration.ConfigurationBuilders
{
public class AwsSsmConfigBuilder : KeyValueConfigBuilder
{
private string BaseParameterPath = "/padnugapp/ApiKeys";
private static IAmazonSimpleSystemsManagement _client;
static AwsSsmConfigBuilder()
{
_client = new AmazonSimpleSystemsManagementClient();
}
public override void Initialize(string name, NameValueCollection config)
{
base.Initialize(name, config);
if (config["ssmPrefix"] == null)
return;
BaseParameterPath = config["ssmPrefix"];
}
public override ICollection<KeyValuePair<string, string>> GetAllValues(string prefix)
{
if (_client == null)
return null;
var request = new GetParametersByPathRequest
{
Path = $"{BaseParameterPath}/{prefix}",
WithDecryption = true,
};
var response = _client.GetParametersByPathAsync(request).Result;
var result = response.Parameters.ToDictionary(param => param.Name, param => param.Value, StringComparer.OrdinalIgnoreCase);
return result;
}
public override string GetValue(string key)
{
if (_client == null)
return null;
var request = new GetParameterRequest
{
Name = $"{BaseParameterPath}/{key}",
WithDecryption = true,
};
var response = _client.GetParameterAsync(request).Result;
return response.Parameter.Value;
}
}
}
The code I put into a web-forms (.aspx) page that renders the two appSettings items in HTML:
TestKey =
<%=(System.Configuration.ConfigurationManager.AppSettings["TestKey"]) %>
<br />
TwitterKey =
<%=(System.Configuration.ConfigurationManager.AppSettings["TwitterKey"]) %>
I can't stress enough that this is just for a demo I'm doing, and not tested in any way, shape or form except on my laptop ;-)
I am trying to create the client to client chat application by using cfwebsocket. I referenced the adobe example. In that example we pass an extra argument on to the publish function. So I passed the receiver id to the publish function, but cannot get that value in the msgHandler function.
<cfoutput>
<cfif !structkeyexists(session,'userName')>
<cflocation url="index.cfm?msg=Please login first" addtoken="false">
</cfif>
<cfdump var="i am chat.cfm" />
Logout
<cfwebsocket name="myworld" onMessage="msgHandler" onOpen="openHandler"/>
<script>
var msgHandler = function(message){
// Get data from the recieved message token
var data = message.data;
console.log(message.data.to);
if(data){
// If data is present write it to the div
var txt=document.getElementById("myDiv");
txt.innerHTML+= data + "<br>";
}
}
var sayHello = function(){
uname = document.getElementById("username").value;
receiver = document.getElementById("selectUser").value;
//var myData = {publishedBy: ''+uname, receiver:''+receiver}
// Calling authenticate from client side. Calling this
//function will invoke onWSAuthenticate from Application.cfc
myworld.authenticate(uname,"password");
myworld.subscribe("chat");
// Client says Hello World
myworld.publish("chat","Hello World! WebSocket is here !!",{to:receiver});
}
var openHandler = function(){
// do nothing
}
</script>
<input type="hidden" name="userName" id="username" value="#session.userName#">
<input id="hello" type="button" value="Say Hello!" onclick="sayHello();">
<div id="myDiv"></div>
<cfset users = Application.usersDAO.read()>
<select name="user" id="selectUser">
<option value="0">Select User</option>
<cfloop query="users">
<option value="#id#">#username#</option>
</cfloop>
</select>
</cfoutput>
You should pass your message and extra argument like a json object.
var sayHello = function()
{
uname = document.getElementById("username").value;
userID = document.getElementById("userID").value;
receiverID = document.getElementById("ToUser").value;
receiverName = document.getElementById("ToUserName").value;
// Calling authenticate from client side. Calling this function will invoke onWSAuthenticate from Application.cfc
myworld.authenticate(uname,"password");
// Client says Hello World
// console.log($('#input').val())
msg = {'username': uname, 'userID' : userID, 'chat': $('#input').val().trim(), 'to':receiverID, 'receiverName' : receiverName };
myworld.publish("world",msg);
$('#input').val('');
}
In msgHandler function you will get message.data.to and message.data.userId. You will store the userId on session scope inside the msgHandler you will compare the session userID and message.data.to. If both are same you will appeand your message on your chat window.
I want to hook the item:renamed event to do some processing. It may take a few minutes though. Are event handlers executed asynchronously or synchronously with normal pipeline execution? Is there a standard Sitecore way to kick this off asynchronously if I need to do that myself?
The only time this handler needs to execute is when an item is renamed in Content Editor.
Sitecore events are executed synchronously. There is a Sitecore Development Toolkit module on Sitecore Marketplace which contains a code for firing events asynchronously which you can easily reuse in your solution Sitecore Development Toolkit.
Here is a part of their code which fires methods asynchronously when the event is fired:
public void OnItemRenamed(object sender, EventArgs args)
{
if (args != null)
{
var item = Event.ExtractParameter(args, 0) as Item;
Assert.IsNotNull(item, "No item in parameters");
var name = Event.ExtractParameter(args, 1) as string;
Assert.IsNotNullOrEmpty(name, "No name in parameters");
DoAsync(() => OnItemRenameAsync(item, name));
}
}
private void OnItemRenameAsync(Item item, string name)
{
var itemRef = new ItemReference(item.Parent);
var itemRefText = itemRef.ToString();
// do some work here
}
Sitecore events are synchronous. You can kick off your long running task as a job. First create a class to handle the event:
namespace MyNamespace
{
public class MyClass
{
public void ItemRenamed (object sender, EventArgs args)
{
Run("LongRenameTask");
}
protected void Run(string methodName, EventArgs args)
{
var item = Event.ExtractParameter(args, 0) as Item;
var name = Event.ExtractParameter(args, 1) as string;
RunJob(methodName, item, name);
}
protected Handle RunJob(string methodName, Item item, string name)
{
var options = new JobOptions(
"Preparing rename job '{0}' for '{1}'".FormatWith(
methodName,
item.ID.ToString()),
"item:renamed",
"shell",
new ItemRenamedManager(item, name),
methodName)
{
WriteToLog = true,
AtomicExecution = true,
};
var job = new Job(options);
JobManager.Start(job);
return job.Handle;
}
}
}
Then create a class to do your work (this will be called on a background thread by Sitecore):
namespace MyNamespace
{
public class ItemRenamedManager
{
protected Item RenamedItem { get; set; }
protected string Name { get; set; }
public ItemRenamedManager(Item item, string name)
{
RenamedItem = item;
Name = name;
}
public void LongRenameTask()
{
// Do your long running task here.
// The property 'RenamedItem' will give you the item
}
}
}
Then patch your event handler in:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<events>
<event name="item:renamed">
<handler type="MyNamespace.MyClass" method="ItemRenamed" />
</event>
</events>
</sitecore>
</configuration>
The above code is cribbed a bit from memory and needs some error handling, but should be pretty close, but this way, your long running task won't block the Content Editor UI.
i have made webservice, and i am trying to consume it using javascript, but when i call the webservice method it gives the error Webservice not defined. I have given reference of it .
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="../WebService.asmx" />
</Services>
</asp:ScriptManager>
my method
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{
CultureInfo cul = new CultureInfo("gu-IN", true);
protected sdData s = new sdData();
protected component comp = new component();
public ClsVB objvb = new ClsVB();
DBAccess dbAccess = new DBAccess();
public WebService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public string SubmitDDIPo(string txtCaseNoDDIPO, int txtDDIPO, int txtAmount, string txtDDDate, string txtBank, string District_Code )
{
javascript method calling
<script type="text/javascript">
function addDDIPO() {
"DDIPOdiv".Obctrl().style.display = "block";
"fadeDiv".Obctrl().style.display = "block";
}
function submitDDIPO()
{
WebService.SubmitDDIPo("txtCaseNoDDIPO".Obctrl().value, "txtDDIPO".Obctrl().value, "txtAmount".Obctrl().value, "txtDDDate".Obctrl().value, "txtBank".Obctrl().value, Session["District_Code"].ToString(), ResultSubmitSucess, ResultFailure);
}
</script>
Is that something i am missing?
please help
Try to uncomment [System.Web.Script.Services.ScriptService].
If the uncommneted attribute doesn't work check the namespaces. ScriptManager create the javascript client proxy whith full path. Ej: namespace1.namespace2.WSClassName.Method(). You can also try to put the client proxy inline to see the js source to easyly find it with ServiceReference.InlineScript property.