Unable to get a mapping value - mapping

I'm trying to implement a small contract to upload file hashes on the blockchain along with the file description and the sender address. I've programmed this small contract :
pragma solidity^0.4.17;
contract hashes {
mapping(uint => string) descriptions;
mapping(uint => address) senderAddresses;
function uploadHash(uint _hash, string _description) public {
require(bytes(descriptions[_hash]).length == 0);
descriptions[_hash] = _description;
senderAddresses[_hash] = msg.sender;
}
function getHash(uint _hash) public returns (address, string){
return (senderAddresses[_hash], descriptions[_hash]);
}
}
I think uploadHash works as expected since when I'm uploading the same hash twice I get a revert. However when I'm trying to use getHash, I don't get any return value. The results are the same when I'm calling from remix or directly from web3.
Thanks in advance !

I believe you're missing the view modifier
function getHash(uint _hash) public view returns (address, string)
Remix will not show the res next to the input boxes unless you use the view modifier.

Related

Mapping lack of understanding

I read a lot about this topic and I understand it quit good.
But, the only thing I don't understand is how in functions developers use it without a function that insert the values.
example:
mapping (uint256=>address) public IdToAddress;
after they defines it I see that they are using in functions like:
function HolderOfNFT(Uint256 Id) public returns (address) {
return IdToAddress[Id];
}
How the mapping has value in the Id key that points to the right address?
Thanks a lot!!
All mapping values are empty by default.
So unless the value is set somewhere in the code, your example would return address(0) for any Id.
You can assign a mapping value the same way as you'd assign it to an array. Examples:
IdToAddress[Id] = address(0x123);
function transfer(address _recipient, uint256 _id) public {
require(IdToAddress[_id] == msg.sender, "You're not the current token owner");
IdToAddress[_id] = _recipient;
}

Unable to make simple Apex class invocable - find custom location record based on coordinate input

I've got a simple class containing a SOQL query that finds the nearest custom location record based on the input of 2 coordinates:
public with sharing class NearestLocation {
#InvocableMethod(label='Get Nearest location' description='From given coordinates the nearest location is returned')
public static List<custom__Location__c> getLocation(List<FlowInput> requests)
{
List<custom__Location__c> locList =
[SELECT id, Name
FROM custom__Location__c WHERE RecordType.Name = 'Synced' AND
DISTANCE(custom__GeoLocation__c, GEOLOCATION(:requests[0].coordlat, :requests[0].coordlng), 'km')<1
ORDER BY DISTANCE(custom__GeoLocation__c, GEOLOCATION(:requests[0].coordlat, :requests[0].coordlng), 'km')
LIMIT 1];
for(custom__Location__c lc : locList)
{
system.debug('~~!~~!~~' + lc.id);
system.debug('~~!~~!~~' + lc.name);
}
return locList;
}
public class FlowInput
{
#InvocableVariable(required=true)
public decimal coordlat;
#InvocableVariable(required=true)
public decimal coordlng;
} }
The above code works as expected when run from Execute Anon:
list <NearestLocation.FlowInput> fi = new list<NearestLocation.FlowInput>();
NearestLocation.FlowInput x1 = new NearestLocation.FlowInput();
x1.coordlat = 53.243213;
x1.coordlng = -1.475886;
fi.add(x1);
NearestLocation.getLocation(fi);
However, I'm trying to get it to be 'invoked' from within a lightning flow, but it fails with a generic 'flow has validation errors'​ message.
lightning flow - apex action
execution log - flow has validation errors
I'm obviously missing something and was wondering if anyone could offer some guidance/thoughts?
try to return List> if you assign the output to a collection variable.
RESOLVED. 
Nothing inheritently wrong with the code....problems were due to unrelated formula in the lightning flow!  Hmmm...note to self...start with a blank canvas!
Thanks for the response Ahmed. It is returning a list:
public static List
return locList;

ASP.NET Custom Localization

I've done quite a bit of research and I'm not sure how I should proceed with this.
Usual localization would change only when the language changes, so Hello for french would be Bonjour but my application needs to have special keywords for for certain users so UserX might say "Hello" needs to be "Allo".
I would like to have resource key with IdentityName_resourceKey and if this key is present take it otherwize fall back to resourceKey.
I'm thinking I need a custom ResourceProvider but my implementation is a simple if statement so I would not want to write a complete resource provider.
I wrote a extension of DisplayName attribute which works fine but this is not very good as I will need one of those for every data annotation attributes and this would not work if I use resources directly in pages or controllers...
public class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
private readonly PropertyInfo _propertyInfo;
public LocalizedDisplayNameAttribute(string resourceKey, Type resourceType) : base(resourceKey)
{
var clientName = CustomMembership.Instance.CurrentUser.Client.Name;
_propertyInfo = resourceType.GetProperty(clientName + "_" + base.DisplayName, BindingFlags.Static | BindingFlags.Public)
?? resourceType.GetProperty(base.DisplayName, BindingFlags.Static | BindingFlags.Public);
}
public override string DisplayName
{
get
{
if (_propertyInfo == null)
{
return base.DisplayName;
}
return (string) _propertyInfo.GetValue(_propertyInfo.DeclaringType, null);
}
}
}
I'm looking for the best way to implement this with the least amount of code..
Thank you!
There is a better way, Data Annotations is your answer!
this is just a sample, you need go more deeper with System.Globalization.CultureInfo and Data Annotations (System.ComponentModel.DataAnnotations)
you can define your model class like this (assuming we have a resource file named CustomResourceValues with a value "strHello")
public class SomeObject(){
<Display(Name:="strHello", ResourceType:=GetType(My.Resources.CustomResourceValues))>
public string HelloMessage{ get; set; }
}
so, in our view the work must do it by the htmlhelper (assuming razor like render engine and the model is type of "SomeObject")
#Html.LabelFor(Function(x) x.HelloMessage)
basic info http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayattribute.resourcetype(v=vs.95).aspx

ASP.NET MVC Validation Help

I'm doing some simple validation inside my Controller I know this would better placed inside something like a service layer but for this I want to keep it inside the Controller
The idea is to check that a valid url is being entered into a url field to display an image, e.g. http://domain.com/myawesomeimage.png would be valid and http://domain.com/ would not be valid.
// ValidateInt has a default value of 0
int ValidateInt = 0;
// If the url entered (if one at all) does not have correct extension then increment the ValidateInt
if (!ArticleToEdit.image.Contains(".jpg"))
ValidateInt++;
if (!ArticleToEdit.image.Contains(".jpeg"))
ValidateInt++;
if (!ArticleToEdit.image.Contains(".png"))
ValidateInt++;
if (!ArticleToEdit.image.Contains(".gif"))
ValidateInt++;
if (!ArticleToEdit.image.Contains(".bmp"))
ValidateInt++;
// if ValidateInt is bigger than 0 then the url is invalid
if (ValidateInt > 0)
ModelState.AddModelError("Image", "Please enter a valid URL.");
EDITED CODE
The problem with your code
Your code is invalid, because your model state will always have at least 4 errors. Even though the URL would be correct. Your code requires that your URL must have all extensions which is of course incorrect. It can only have one. At most.
The solution
Use DataAnnotations instead and use regular expression validator. You're obviously already using some application model class called ArticleToCreate. You'll have to put data annotations attribute on the image property (one more observation: keey property names with Pascal casing so it's the same as .net):
public class ArticleToCreate
{
[RegularExpression(#"...")] // add regular expression that fulfils your requirements
public string Image { get; set; }
...
}
Then it all depends how complicated your regular expression is. The easiest one for your needs could be just that it starts with an http:// and end with the correct extension:
^http:\/\/.+\.(?:png|jpe?g|gif|bmp)$
And if you're directly providing your class instance to controller action it will get automatically validated for you without any additional code. This way you won't be able to forget to validate your objects manually.
Consider this controller action that automatically validates your model class object instance by validators defined on it (as per validator definition I've written above):
public ActionResult Create(ArticleToCreate data)
{
if (!this.ModelState.IsValid)
{
// handle invalid object
}
// handle valid object
}
This way your actions will focus on the processing part which is their main objective instead of focusing on too many aspects of your business process like validation for instance.
Shorter code = simpler code = easier to maintain = less bugs = less work = happy clients
Why not create custom ValidationAttributes (from DataAnnotations) and allow the Validation Engine do the work for you rather than worrying about where to put your logic?
I'm guessing it would look something like:
[AttributeUsage(AttributeTargets.Property |
AttributeTargets.Field, AllowMultiple = false)]
public class ValidImageUrlAttribute : ValidationAttribute
{
public string ErrorMessage { get; set; }
public override bool IsValid(object value)
{
var url = value as string;
if(!url.Contains(".jpg") || !url.Contains(".jpeg")
|| !url.Contains(".gif") || !url.Contains(".bmp")
|| !url.Contains(".png"))
{
return false;
}
return true;
}
public override string FormatErrorMessage(string name)
{
return ErrorMessage ?? base.FormatErrorMessage(name);
}
}
And then you could decorate your Model:
[Required(ErrorMessage = "Image URL is required.")]
[ValidImageUrl(ErrorMessage = "Valid Image URL is required.")]
public string ImageUrl { get; set; }
changed if (validate1 > 0) and it works fine :)

Json and Circular Reference Exception

I have an object which has a circular reference to another object. Given the relationship between these objects this is the right design.
To Illustrate
Machine => Customer => Machine
As is expected I run into an issue when I try to use Json to serialize a machine or customer object. What I am unsure of is how to resolve this issue as I don't want to break the relationship between the Machine and Customer objects. What are the options for resolving this issue?
Edit
Presently I am using Json method provided by the Controller base class. So the serialization I am doing is as basic as:
Json(machineForm);
Update:
Do not try to use NonSerializedAttribute, as the JavaScriptSerializer apparently ignores it.
Instead, use the ScriptIgnoreAttribute in System.Web.Script.Serialization.
public class Machine
{
public string Customer { get; set; }
// Other members
// ...
}
public class Customer
{
[ScriptIgnore]
public Machine Machine { get; set; } // Parent reference?
// Other members
// ...
}
This way, when you toss a Machine into the Json method, it will traverse the relationship from Machine to Customer but will not try to go back from Customer to Machine.
The relationship is still there for your code to do as it pleases with, but the JavaScriptSerializer (used by the Json method) will ignore it.
I'm answering this despite its age because it is the 3rd result (currently) from Google for "json.encode circular reference" and although I don't agree with the answers (completely) above, in that using the ScriptIgnoreAttribute assumes that you won't anywhere in your code want to traverse the relationship in the other direction for some JSON. I don't believe in locking down your model because of one use case.
It did inspire me to use this simple solution.
Since you're working in a View in MVC, you have the Model and you want to simply assign the Model to the ViewData.Model within your controller, go ahead and use a LINQ query within your View to flatten the data nicely removing the offending circular reference for the particular JSON you want like this:
var jsonMachines = from m in machineForm
select new { m.X, m.Y, // other Machine properties you desire
Customer = new { m.Customer.Id, m.Customer.Name, // other Customer properties you desire
}};
return Json(jsonMachines);
Or if the Machine -> Customer relationship is 1..* -> * then try:
var jsonMachines = from m in machineForm
select new { m.X, m.Y, // other machine properties you desire
Customers = new List<Customer>(
(from c in m.Customers
select new Customer()
{
Id = c.Id,
Name = c.Name,
// Other Customer properties you desire
}).Cast<Customer>())
};
return Json(jsonMachines);
Based on txl's answer you have to
disable lazy loading and proxy creation and you can use the normal methods to get your data.
Example:
//Retrieve Items with Json:
public JsonResult Search(string id = "")
{
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
var res = db.Table.Where(a => a.Name.Contains(id)).Take(8);
return Json(res, JsonRequestBehavior.AllowGet);
}
Use to have the same problem. I have created a simple extension method, that "flattens" L2E objects into an IDictionary. An IDictionary is serialized correctly by the JavaScriptSerializer. The resulting Json is the same as directly serializing the object.
Since I limit the level of serialization, circular references are avoided. It also will not include 1->n linked tables (Entitysets).
private static IDictionary<string, object> JsonFlatten(object data, int maxLevel, int currLevel) {
var result = new Dictionary<string, object>();
var myType = data.GetType();
var myAssembly = myType.Assembly;
var props = myType.GetProperties();
foreach (var prop in props) {
// Remove EntityKey etc.
if (prop.Name.StartsWith("Entity")) {
continue;
}
if (prop.Name.EndsWith("Reference")) {
continue;
}
// Do not include lookups to linked tables
Type typeOfProp = prop.PropertyType;
if (typeOfProp.Name.StartsWith("EntityCollection")) {
continue;
}
// If the type is from my assembly == custom type
// include it, but flattened
if (typeOfProp.Assembly == myAssembly) {
if (currLevel < maxLevel) {
result.Add(prop.Name, JsonFlatten(prop.GetValue(data, null), maxLevel, currLevel + 1));
}
} else {
result.Add(prop.Name, prop.GetValue(data, null));
}
}
return result;
}
public static IDictionary<string, object> JsonFlatten(this Controller controller, object data, int maxLevel = 2) {
return JsonFlatten(data, maxLevel, 1);
}
My Action method looks like this:
public JsonResult AsJson(int id) {
var data = Find(id);
var result = this.JsonFlatten(data);
return Json(result, JsonRequestBehavior.AllowGet);
}
In the Entity Framework version 4, there is an option available: ObjectContextOptions.LazyLoadingEnabled
Setting it to false should avoid the 'circular reference' issue. However, you will have to explicitly load the navigation properties that you want to include.
see: http://msdn.microsoft.com/en-us/library/bb896272.aspx
Since, to my knowledge, you cannot serialize object references, but only copies you could try employing a bit of a dirty hack that goes something like this:
Customer should serialize its Machine reference as the machine's id
When you deserialize the json code you can then run a simple function on top of it that transforms those id's into proper references.
You need to decide which is the "root" object. Say the machine is the root, then the customer is a sub-object of machine. When you serialise machine, it will serialise the customer as a sub-object in the JSON, and when the customer is serialised, it will NOT serialise it's back-reference to the machine. When your code deserialises the machine, it will deserialise the machine's customer sub-object and reinstate the back-reference from the customer to the machine.
Most serialisation libraries provide some kind of hook to modify how deserialisation is performed for each class. You'd need to use that hook to modify deserialisation for the machine class to reinstate the backreference in the machine's customer. Exactly what that hook is depends on the JSON library you are using.
I've had the same problem this week as well, and could not use anonymous types because I needed to implement an interface asking for a List<MyType>. After making a diagram showing all relationships with navigability, I found out that MyType had a bidirectional relationship with MyObject which caused this circular reference, since they both saved each other.
After deciding that MyObject did not really need to know MyType, and thereby making it a unidirectional relationship this problem was solved.
What I have done is a bit radical, but I don't need the property, which makes the nasty circular-reference-causing error, so I have set it to null before serializing.
SessionTickets result = GetTicketsSession();
foreach(var r in result.Tickets)
{
r.TicketTypes = null; //those two were creating the problem
r.SelectedTicketType = null;
}
return Json(result);
If you really need your properties, you can create a viewmodel which does not hold circular references, but maybe keeps some Id of the important element, that you could use later for restoring the original value.

Resources