truffle migrate only migrating first contract, not the second - javascript

the command "truffle migrate" works properly (no errors) but only migrates "Migrations.sol". It does not even attempt to migrate with 2_deploy_contracts.js
1_initial_migration.js :
var Migrations = artifacts.require("./Migrations.sol");
module.exports = function(deployer) {
deployer.deploy(Migrations);
};
Migrations.sol:
enter code herepragma solidity ^0.4.25;
contract Migrations {
address public owner;
uint public last_completed_migration;
modifier restricted() {
if (msg.sender == owner) _;
}
function Migration() public {
owner = msg.sender;
}
function setCompleted(uint completed) restricted public{
last_completed_migration = completed;
}
function upgrade(address new_address) restricted public{
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
2_deploy_contracts.js:
var Election = artifacts.require("./Election.sol");
module.exports = function(deployer) {
deployer.deploy(Election);
};
Election.sol:
pragma solidity ^0.4.25;
contract Election {
// Store candidate
// Read candidate
string public candidate;
// Constructor
// Our constructor will be run when the contract gets deployed, so must be public
constructor() public{
candidate = "Candidate 1";
}
}

Solution: I deleted my project folder and rebuilt it. This fixed it. Not sure exactly what the issue was.

Related

Calling a smart contract function using metamask with ether.js

I'm completely new to both blockchain and JavaScript.
I'm trying to create a simple web page where people could generate a "wedding" smart contract that basically store their 2 names. For this I have created a WeddingCerficate contract which store the names and have a getter function, and a WeddingCertificateFactory That enable me to generate a WeddingCertificate. You can find the code of the smart contracts in solidity below.
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
contract WeddingCertificate{
string private spouse1;
string private spouse2;
constructor(string memory _spouse1, string memory _spouse2) {
spouse1 = _spouse1;
spouse2 = _spouse2;
}
function getSpouses() public view returns (string memory,string memory) {
return (spouse1,spouse2);
}
}
contract WeddingCertificateFactory{
event Wedding(string _spouse1, string _spouse2, address indexed contract_adress );
function Unite(string memory _spouse1, string memory _spouse2)public returns (bool success) {
WeddingCertificate wedding = new WeddingCertificate(_spouse1, _spouse2);
emit Wedding(_spouse1,_spouse2 , address(wedding));
return true ;
}
}
I deployed the WeddingCertificateFactory on Goerli Tesnet. And now I'm trying to make a function in javascript (using ether.js) to enable a user to create his own weddingCertificate directly on a web interface.
For this I wrote the function below but for some reasons this only generates the new Wedding certificate once out 20. And even when it actually work, the two last print aren't visible in the console.
I do not get any error (at least that I can see in the console) when I test the function and nothing happen.
I'm not familiar with async in JavaScript, I also tried the .then( syntax but I didn't notice any difference.
async function CreateWedding(){
const spouse1 = document.getElementById("spouse1").value;
const spouse2 = document.getElementById("spouse2").value;
if (spouse1.length > 0 && spouse2.length >0) {
console.log(`spouse 1: ${spouse1} , spouse2 : ${spouse2} `);
const ethereum = window.ethereum ;
const accounts = await ethereum.request({
method: "eth_requestAccounts",
});
const provider = new ethers.providers.Web3Provider(ethereum, "any");
const walletAddress = accounts[0];
const signer = provider.getSigner(walletAddress);
let abi = [
" function Unite(string memory _spouse1, string memory _spouse2)"
];
const contractAddress = "0x2556Ff7f7F1c013bBB60bD120E1828032Cd84cc4"; //WeddingFactory Contract
const contract = new ethers.Contract(contractAddress, abi, signer);
console.log("sending the contract");
tx = await contract.Unite(spouse1,spouse2);
console.log(tx);
console.log("finished");
} else {
alert("Please enter 2 names");
}
}
Try creating your abi method in web3client.app.
It has code generater for ether.js which yoy can use directly in your app.
If there is an actual issue in your contract it would fail there itself.

Creation of CustomToken errored: VM error: revert

I new to solidity so could you guys please help me thanks? I tried to deploy the contract will ETH Value but always got the error "The transaction has been reverted to the initial state.
The called function should be payable if you send value and the value you send should be less than your current balance.".
Is there any way to fix this?
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract CustomToken is ERC20 {
constructor(string memory name, string memory symbol) ERC20(name, symbol){
_mint(msg.sender, 1000000 * 10 ** 18);
}
}
contract Uniswap {
// Custom tokens to be initialiazed
string[] public tokens = ["CoinA", "CoinB", "CoinC"];
// map to maintain the tokens and its instances
mapping(string => ERC20) public tokenInstanceMap;
// 1 CoinA/CoinB/COinC = 0.0001 eth
uint256 ethValue = 100000000000000;
// 0.0001 eth = 1 CoinA/CoinB/CoinC
// 1 CoinA/CoinB/CoinC = 1 CoinA/CoinB/CoinC
constructor() {
for (uint i=0; i<tokens.length; i++) {
CustomToken token = new CustomToken(tokens[i], tokens[i]);
tokenInstanceMap[tokens[i]] = token;
}
}
function getBalance(string memory tokenName, address _address) public view returns (uint256) {
return tokenInstanceMap[tokenName].balanceOf(_address);
}
function getTotalSupply(string memory tokenName) public view returns (uint256) {
return tokenInstanceMap[tokenName].totalSupply();
}
function getName(string memory tokenName) public view returns (string memory) {
return tokenInstanceMap[tokenName].name();
}
function getTokenAddress(string memory tokenName) public view returns (address) {
return address(tokenInstanceMap[tokenName]);
}
function getEthBalance() public view returns (uint256) {
return address(this).balance;
}
function swapEthToToken(string memory tokenName) public payable returns (uint256) {
uint256 inputValue = msg.value;
uint256 outputValue = (inputValue / ethValue) * 10 ** 18; // Convert to 18 decimal places
require(tokenInstanceMap[tokenName].transfer(msg.sender, outputValue));
return outputValue;
}
}
I try with 0 ETH and it worked fine!
(https://i.stack.imgur.com/UtLNt.png)
However, with 1 ETH and it got error message
(https://i.stack.imgur.com/MsjE0.png)
A function needs to use the payable modifier in order to accept ETH.
When you're deploying a contract, it executes the constructor.
constructor(string memory name, string memory symbol) ERC20(name, symbol) payable {
_mint(msg.sender, 1000000 * 10 ** 18);
}

Create Solidity contract instance as a result of long running process

How can I write to the blockchain after an undetermined, time-consuming execution result?
Situation:
Web Client (NextJS): User requests a long running process that can take up to 1 hour to complete. As a result of this transaction, a new contract instance should be written to the blockchain. We can't expect the client to stick around waiting => use a NodeJS or cloud function to delegate the long running task. Metamask on the client will define the contract owner.
Planning to use NextJS to route to a Moralis Cloud Fx to kick off the long running task. The result of this long running task will be digital content to store to the blockchain.
Constraints/Problem:
Can’t have the user wait for the process to complete
Metamask runs on the client
Need Moralis Cloud Fx or NodeJS to have access to the owner to instantiate the contract at an undetermined future point in time.
From: sequencediagram.org
title Long Running Task to Blockchain
actor User
User->UI:User Request
UI->NodeServer: Delegate Slow Tasks
activate NodeServer
NodeServer->RestService: Start slow process
activate RestService
RestService-->NodeServer: Confirmation ID
NodeServer-->UI: Confirmation ID
UI->Blockchain: Create empty contract
RestService->NodeServer: Result = Data for blockchain
deactivate RestService
NodeServer->Blockchain: **Public?** Contract.setRestResult(Result)
deactivate NodeServer
Here is how I was planning to approach setting up the contract that would straddle the client and server.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract EncryptionNFT is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private tokenCounter;
uint256 public fee_wei;
bool public isLocked; // has a user paid to access the resource?
string private confirmationId; // long temporary password
string private sensitiveData; // data produced by long running process
address public encryptionService; // service responsible for producing the sensitive data
address public licensor; // licensed process
uint256 public tokenID; // distinct contract id
bool private isMutexed = false; // Reentrancy guard
bool private isSensitiveDataSet = false; // Asserts can only be set 1 time
event unlockPaid(address receiver, uint256 amount);
event withdrawlMade(address receiver, uint256 amount);
constructor(string memory name, uint256 _fee_gwei, string memory _confirmationId, address _encryption_service, address _licensor)
ERC721(name, "DataX")
{
fee_wei = _fee_gwei * 1000000000; // assert numbers are in WEI
isLocked = true; // lock contract by default since data not available => owner shouldn't have to pay unless successful
confirmationId = _confirmationId; // assign temporary password
encryptionService = _encryption_service; // assign addresses for payments
licensor = _licensor; // assign addresses for payments
tokenID = tokenCounter.current(); // Set/Mint with distinct token id
_safeMint(msg.sender, tokenID);
tokenCounter.increment();
}
function unlock() public payable {
require(isLocked == true, "Contract already unlocked.");
require(msg.value >= fee_wei, "Not enough WEI to unlock NFT.");
require(isMutexed == false, "Reentrant call detected!");
isMutexed = true;
// DO PAYMENTS
uint256 rcv_payment = msg.value;
uint256 licensor_cut = rcv_payment / 10;
uint256 encryptor_cut = rcv_payment - licensor_cut;
(bool is_encryptor_success, ) = payable(encryptionService).call{value: encryptor_cut}("");
require(is_encryptor_success, "Encryptor transfer failed.");
emit unlockPaid(encryptionService, encryptor_cut);
(bool is_licensor_success, ) = payable(licensor).call{value: licensor_cut}("");
require(is_licensor_success, "Licensor transfer failed.");
emit unlockPaid(licensor, licensor_cut);
isLocked = false;
isMutexed = false;
}
function withdraw() public payable {
require(msg.sender == ownerOf(tokenID), "Only owner may withdraw.");
require(isLocked == false, "Contract must be unlocked.");
require(isMutexed == false, "Reentrant call detected!");
isMutexed = true;
// DO PAYMENTS
uint256 rcv_payment = msg.value;
uint256 nft_service_cut = rcv_payment / 10;
uint256 licensor_cut = nft_service_cut / 10;
uint256 encryptor_cut = rcv_payment - licensor_cut;
uint256 nft_owner_cut = rcv_payment - nft_service_cut;
(bool is_encryptor_success, ) = payable(encryptionService).call{value: encryptor_cut}("");
require(is_encryptor_success, "Encryptor transfer failed.");
emit withdrawlMade(encryptionService, encryptor_cut);
(bool is_licensor_success, ) = payable(licensor).call{value: licensor_cut}("");
require(is_licensor_success, "Licensor transfer failed.");
emit withdrawlMade(licensor, licensor_cut);
(bool is_nft_owner_success, ) = payable(ownerOf(tokenID)).call{value: nft_owner_cut}("");
require(is_nft_owner_success, "NFT Owner transfer failed.");
emit withdrawlMade(ownerOf(tokenID), nft_owner_cut);
isMutexed = false;
}
function setTokenURI(string memory _tokenURI) public {
require(_isApprovedOrOwner(_msgSender(), tokenID), "ERC721: transfer caller is not owner nor approved.");
_setTokenURI(tokenID, _tokenURI);
}
// Here's how I was planning to allow a server-side process to set the data on REST service completion (slow task)
function setSensitiveData(string memory _confirmationId, string memory _sensitiveData) public {
require(keccak256(bytes(_confirmationId)) == keccak256(bytes(confirmationId)), "Confirmation ID does not match.");
require(isSensitiveDataSet == false, "Sensitive Data has already been set");
sensitiveData = _sensitiveData;
isSensitiveDataSet = true;
}
function getSensitiveData() public view returns (string memory){
require(isSensitiveDataSet == true, "Sensitive Data must be set first.");
require(msg.sender == encryptionService, "Only encryption service accessible.");
return sensitiveData;
}
}
Edit I just found Moralis has a session that appears to allow server side access as a corresponding user. Has anyone played with this before? Would it work for this use case?
Moralis Docs

How can I create clock auction with javascript from smart contracts?

i am pretty new for this area but I wanna create a dapp with auction function. is there any help how I can start that ? I start to create NFT marketplace but I am stuck now with this level, I can not get implementation from my smart contract to javascript.
this is my contract
pragma solidity >=0.7.0 <0.9.0;
contract SimpleAuction{
address payable public beneficiary;
uint public auctionEndTime;
address public highestBidder;
uint public highestBid;
mapping(address => uint) public pendingReturns;
bool ended = false;
event HighestBidIncrease(address bidder, uint amount);
event AuctionEnded(address winner, uint amount);
constructor(uint _biddingTime, address payable _beneficiary){
beneficiary = _beneficiary;
auctionEndTime = block.timestamp + _biddingTime;
}
function bid() public payable{
if (block.timestamp > auctionEndTime){
revert("The auction has already ended");
}
if (msg.value <= highestBid){
revert("There is alreay a higher or equal bid");
}
if (highestBid != 0){
pendingReturns[highestBidder] += highestBid;
}
highestBidder = msg.sender;
highestBid = msg.value;
emit HighestBidIncrease(msg.sender, msg.value);
}
function withdraw() public returns (bool){
uint amount = pendingReturns[msg.sender];
if(amount > 0){
pendingReturns[msg.sender] = 0;
if(!payable(msg.sender).send(amount)){
pendingReturns[msg.sender] = amount;
return false;
}
}
return true;
}
function auctionEnd() public{
if (block.timestamp < auctionEndTime){
revert ("The auction has not ended yet");
}
if (ended){
revert("the function auctionEnded has already been called");
}
ended = true;
emit AuctionEnded(highestBidder, highestBid);
beneficiary.transfer(highestBid);
}
}
i see that you took this code from the moralis auction tutorial,
1- this code is not useful for your marketplace as it is right now since this smart contracts starts the auction when the contract is DEPLOYED (which means when u run truffle migrate)
2- your smart contract needs 2 parameters to be deployed anyway which are the beneficiary address and the time of the auction, have you been able to deploy it correctly?? if not you have to add to your migrations this code :
const Auction = artifacts.require("Auction");
module.exports = function (deployer) {
deployer.deploy(Auction,"120","0xF17A576C88EE43D30b67Eb412e2D588e2866102F");
};
where the 120 is the time in seconds and the address is the beneficiary address, ofc this is hardcoded for exemple purposes, you can input the values u like from certain variables
3- this smart contract is good for learning the logic of an auction but is useless for your actual project

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