How to Make a app acording to language change - mvvm

I developed an app that can support two languages. Going beyond that if I need this app for support with many languages. let assume ten languages how to accomplish this requirement
Now what I do is Hard cording it with both languages I used and then retrieve it. If I going to do that for ten languages it does not sound good is there any smart way to do this.
as an example;
I doing with MVVM pattern In my View Model. I use the property and do this its simple way of doing
public string GetPageTitle => AppResources.VitalSignsViewPage_Title;
and my resource file I have two data set if the language has changed it will use write dataset this is what I am doing right now is there any proper smart way to this to many languages.

There is some solutions to achive this. I recommend to you basic
solution ,
Here is an interface for Language Service (It is optionally , if you
using Dependency Injection):
public interface ILanguageService
{
string GetString(string text);
void ChangeLanguage(bool isALang);
bool IsALanguage();
}
You can create a service for localization :
namespace Service.Language
{
public sealed class LanguageService : ILanguageService
{
List<LanguageRow> LanguageList;
private bool IsFirstLang;
public LanguageService()
{
LanguageList = JsonHelper.ReadJSON<List<LanguageRow>>("Service.Language.MultiLanguage.json", typeof(LanguageService));
IsFirstLang = true;
}
public void ChangeLanguage(bool IsFirstLang)
{
IsFirstLang = !IsFirstLang;
}
public bool IsALangueage()
{
return IsFirstLang;
}
public string GetString(string text)
{
string result;
try
{
var row = LanguageList.FirstOrDefault(i => i.Code.Equals(text));
result = IsFirstLang? row.Values[0] : row.Values[1];
}
catch
{
result = text;
}
return result;
}
}
}
Here is a model to serialization for json :
public class LanguageRow
{
public LanguageRow()
{
Values = new List<string>();
}
public string Code { get; set; }
public List<string> Values { get; set; }
}
At last, here is json file : (EN-FR)
[
{
"Code": "VitalSignsViewPage_Title",
"Values": [ "Page Title", "Titre de la page" ]
},
{
"Code": "VitalSignsViewPage_SubTitle",
"Values": [ "Sub Title", "Sous-titre" ]
},
{
"Code": "VitalSignsViewPage_SubSubTitle",
"Values": [ "Sub Sub Title", "Sous sous-titre" ]
}
]
You can access translations like :
ILanguageService _langService = new LangService()
_langService.GetString(AppResources.VitalSignsViewPage_Title);

Related

Use Smart contracts mint function in nethereum with parameters

I try to build a game in unity, in which you can earn a blockchain token by minting it.
The API of the mint function looks like this:
{
"constant": false,
"inputs": [{"internalType": "address","name": "account","type": "address"}, {"internalType": "uint256","name": "amount","type": "uint256"}],
"name": "mint",
"outputs": [{"internalType": "bool","name": "","type": "bool"}],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
I first checked the approach in the flappy-bird-documentation and tried to change the set to score as follows:
public Function mintToken() {
return contract.GetFunction("mint");
}
CreateMintTokenTransactionInput(string addressFrom, string addressOwner, string privateKey, string adress , BigInteger amount, HexBigInteger gas = null, HexBigInteger valueAmount = null) {
var function = mintToken ();
return function.CreateTransactionInput(addressFrom, gas, valueAmount, adress, amount);
}
In the Start method of unity I go:
var transactionInput = CreateMintTokenTransactionInput(_userAddress, _addressOwner, _privateKey, adress, amount);
var transactionSignedRequest = new TransactionSignedUnityRequest(_url, GameControl.instance.Key, _userAddress);
//send and wait
yield return transactionSignedRequest.SignAndSendTransaction(transactionInput);
But the parameters of the function seem to be wrong.
I wonder if there is an easier way to do this or how I could fix my approach.
In more general terms: How can I call an arbitrary smart contract method with parameters in Ethereum?
The next Problem ist that i dont get a transactionHash and I am not sure how to Debug this:
yield return transactionMintRequest.SignAndSendTransaction(mint, contractAddress);
if (transactionMintRequest.Exception != null)
{
Debug.Log(transactionMintRequest.Exception.Message);
yield break;
}
Debug.Log(transactionMintRequest);
var transactionMintHash = transactionMintRequest.Result;
Debug.Log("Transfer txn hash:" + transactionMintHash);
Following the documentation http://docs.nethereum.com/en/latest/unity3d-smartcontracts-getting-started/#transfer-transaction
The simplest thing to do is to create first your Mint Function, this has been code generated using the http://playground.nethereum.com/
public partial class MintFunction : MintFunctionBase { }
[Function("mint", "bool")]
public class MintFunctionBase : FunctionMessage
{
[Parameter("address", "account", 1)]
public virtual string Account { get; set; }
[Parameter("uint256", "amount", 2)]
public virtual BigInteger Amount { get; set; }
}
Then create your TransactionSignedUnityRequest as follows:
var transactionMintRequest = new TransactionSignedUnityRequest(url, privateKey, "YOURCHAINID");
var mint = new MintFunction
{
Account= account,
Amount = amount,
};
yield return transactionMintRequest.SignAndSendTransaction(mint, contractAddress);
var transactionMintHash = transactionMintRequest.Result;

How to map only changed properties using Automapper and Entity Framework

I know that this question had been asked already, but those answers didn't work for me. So, I beg not to close this question! 😎
The goal is simple:
Get entity from database using Entity Framework.
Pass this entity to MVC view.
Edit entity on the page.
Save entity.
What I have:
Entities
• Client relates to table in database.
• ClientDto is the same as Client, but without Comment property (to emulate situation when user must not see this field).
public class Client
{
public string TaskNumber { get; set; }
public DateTime CrmRegDate { get; set; }
public string Comment { get; set; }
}
public class ClientDto
{
public string TaskNumber { get; set; }
public DateTime CrmRegDate { get; set; }
}
Database table
CREATE TABLE dbo.client
(
task_number varchar(50) NOT NULL,
crm_reg_date date NOT NULL,
comment varchar(3000) NULL
);
-- Seeding
INSERT INTO dbo.client VALUES
('1001246', '2010-09-14', 'comment 1'),
('1001364', '2010-09-14', 'comment 2'),
('1002489', '2010-09-22', 'comment 3');
MVC controller
public class ClientsController : Controller
{
private readonly ILogger logger;
private readonly TestContext db;
private IMapper mapper;
public ClientsController(TestContext db, IMapper mapper, ILogger<ClientsController> logger)
{
this.db = db;
this.logger = logger;
this.mapper = mapper;
}
public IActionResult Index()
{
var clients = db.Clients;
var clientsDto = mapper.ProjectTo<ClientDto>(clients);
return View(model: clientsDto);
}
public async Task<IActionResult> Edit(string taskNumber)
{
var client = await db.Clients.FindAsync(taskNumber);
return View(model: client);
}
[HttpPost]
public async Task<IActionResult> Edit(ClientDto clientDto)
{
// For now it's empty - it'll be used for saving entity
}
}
Mappings:
builder.Services
.AddAutoMapper(config =>
{
config.CreateMap<Client, ClientDto>();
config.CreateMap<ClientDto, Client>();
}
Helper (outputs entity entry as JSON)
internal static class EntititesExtensions
{
internal static string ToJson<TEntity>(this EntityEntry<TEntity> entry) where TEntity: class
{
var states = from member in entry.Members
select new
{
State = Enum.GetName(member.EntityEntry.State),
Name = member.Metadata.Name,
Value = member.CurrentValue
};
var json = JsonSerializer.SerializeToNode(states);
return json.ToJsonString(new JsonSerializerOptions { WriteIndented = true });
}
}
THE PROBLEM
I need to map only changed properties from ClientDto to Client in Edit(ClientDto clientDto).
Which solutions were used
Solution 1
Just map ClientDto to Client:
[HttpPost]
public async Task<IActionResult> Edit(ClientDto clientDto)
{
var client = mapper.Map<Client>(clientDto);
logger.LogInformation(db.Entry(client).ToJson());
db.Update(client);
await db.SaveChangesAsync();
return View(viewName: "Success");
}
The problem with this code is that absolutely new Client entity gets created which properties will be filled by ClientDto. This means that Comment property will be NULL and it will make NULL the column comment in database. In general case, all hidden properties (i.e. absent in DTO) will have their default values. Not good.
Output:
[
{
"State": "Detached",
"Name": "TaskNumber",
"Value": "1001246"
},
{
"State": "Detached",
"Name": "Comment",
"Value": null
},
{
"State": "Detached",
"Name": "CrmRegDate",
"Value": "2010-09-15T00:00:00"
}
]
Solution 2
I tried to use the solution from the answer I mentioned above:
public static IMappingExpression<TSource, TDestination> MapOnlyIfChanged<TSource, TDestination>(this IMappingExpression<TSource, TDestination> map)
{
map.ForAllMembers(source =>
{
source.Condition((sourceObject, destObject, sourceProperty, destProperty) =>
{
if (sourceProperty == null)
return !(destProperty == null);
return !sourceProperty.Equals(destProperty);
});
});
return map;
}
In configuration:
builder.Services
.AddAutoMapper(config =>
{
config.CreateMap<Client, ClientDto>();
config.CreateMap<ClientDto, Client>().MapOnlyIfChanged();
});
Running same code as in solution 1, we get the same output (Comment is null):
[
{
"State": "Detached",
"Name": "TaskNumber",
"Value": "1001246"
},
{
"State": "Detached",
"Name": "Comment",
"Value": null
},
{
"State": "Detached",
"Name": "CrmRegDate",
"Value": "2010-09-15T00:00:00"
}
]
Not good.
Solution 3
Let's take another route:
Obtain entity from database.
Use non-generic Map in order to overwrite the values from ClientDto to Client from database.
Tune mapping configuration in order to skip properties which values are equal.
builder.Services
.AddAutoMapper(config =>
{
config.CreateMap<Client, ClientDto>();
config.CreateMap<ClientDto, Client>()
.ForMember(
dest => dest.TaskNumber,
opt => opt.Condition((src, dest) => src.TaskNumber != dest.TaskNumber))
.ForMember(
dest => dest.TaskNumber,
opt => opt.Condition((src, dest) => src.CrmRegDate != dest.CrmRegDate));
});
[HttpPost]
public async Task<IActionResult> Edit(ClientDto clientDto)
{
var dbClient = await db.Clients.FindAsync(clientDto.TaskNumber);
logger.LogInformation(db.Entry(dbClient).ToJson());
mapper.Map(
source: clientDto,
destination: dbClient,
sourceType: typeof(ClientDto),
destinationType: typeof(Client)
);
logger.LogInformation(db.Entry(dbClient).ToJson());
db.Update(dbClient);
await db.SaveChangesAsync();
return View(viewName: "Success");
}
This finally works, but it has problem - it still modifies all properties. Here's the output:
[
{
"State": "Modified",
"Name": "TaskNumber",
"Value": "1001246"
},
{
"State": "Modified",
"Name": "Comment",
"Value": "comment 1"
},
{
"State": "Modified",
"Name": "CrmRegDate",
"Value": "2010-09-15T00:00:00"
}
]
So, how to make Automapper update only modified properties? 😐
You do not need to call context.Update() explicitly.
When loading entity, EF remember every original values for every mapped property.
Then when you change property, EF will compare current properties with original and create appropriate update SQL only for changed properties.
For further reading: Change Tracking in EF Core

how to search any keyword from string using jfce AutoCompleteField

I have swt text where in I have written like "new AutoCompleteField (textSearch,new TextContentProvider(), searchList); it works but it finds the strings start with expression. I want to create my own proposal provider where i can write something if my string contains any keyword, i should get autoComplete popup.
You can't use the existing AutoCompleteField for this since you need to change the content proposal provider.
A suitable IContentProposalProvider would be something like:
public class AnyPositionContentProposalProvider implements IContentProposalProvider
{
private final String [] proposals;
public AnyPositionContentProposalProvider(String [] theProposals)
{
proposals = theProposals;
}
#Override
public IContentProposal [] getProposals(String contents, int position)
{
List<IContentProposal> result = new ArrayList<>();
for (String proposal : proposals) {
if (proposal.contains(contents)) {
result.add(new ContentProposal(proposal));
}
}
return result.toArray(new IContentProposal [result.size()]);
}
}
The following methods set this up to work like AutoCompleteField:
// Installs on a Text control
public static void installAnyPositionMatch(Text control, String [] proposals)
{
installAnyPositionMatch(control, new TextContentAdapter(), proposals);
}
// Install on any control with a content adapter
public static void installAnyPositionMatch(Control control, IControlContentAdapter controlContentAdapter, String [] proposals)
{
IContentProposalProvider proposalProvider = new AnyPositionContentProposalProvider(proposals);
ContentProposalAdapter adapter = new ContentProposalAdapter(control, controlContentAdapter, proposalProvider, null, null);
adapter.setPropagateKeys(true);
adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
}

HippoCMS Rest service does not return image links

I'm a new bee to Hippo CMS. I'm working on version 10 and I'm using angularJS service to consume the rest url for "banners" I created through HippoCms.
This is my Rest URL for Banners created via Hippo's Rest Api Manager:
http://localhost:8080/site/stbetrest/Banner?_type=json
and the reponse I'm getting when consumed the link is:
{
"pageSize": 10,
"total": 3,
"items": [
{
"content": "<![CDATA[\r\n\r\n <p>Banner description</p>\r\n\r\n \r\n]]>",
"title": "Sample banner"
},
{
"content": "<![CDATA[<p>10 Simple Steps to Green Your Office:</p>\n\n<p> </p>\n\n<p>
<img src=\"/site/pagenotfound\" /></p>]]>",
"title": "10 Simple Steps to Green Your Office"
},
{
"content": "<![CDATA[<p>How to Green Your Dorm Room</p>]]>",
"title": "How to Green Your Dorm Room"
}
],
"currentPage": 1,
"totalPages": 1
}
The Problem here is I can't see the Images I used inside the banner documents in Hippo. I want to get those Images/links to load them into a carousel created in AngularJs. Please guide me how to generate the images also into the above banner response.
UPDATE:
All though via the 'localhost:8080/cms' it shows uploaded images, but can not access the image via response:
#XmlRootElement(name = "banner")
#XmlAccessorType(XmlAccessType.NONE)
#HippoEssentialsGenerated(internalName = "gogreen:bannerdocument")
#Node(jcrType = "gogreen:bannerdocument")
public class Banner extends BaseDocument {
#XmlElement
#HippoEssentialsGenerated(internalName = "gogreen:title")
public String getTitle() {
return getProperty("gogreen:title");
}
#XmlJavaTypeAdapter(HippoHtmlAdapter.class)
#XmlElement
#HippoEssentialsGenerated(internalName = "gogreen:content")
public HippoHtml getContent() {
return getHippoHtml("gogreen:content");
}
#HippoEssentialsGenerated(internalName = "gogreen:link")
public HippoBean getLink() {
return getLinkedBean("gogreen:link", HippoBean.class);
}
#XmlJavaTypeAdapter(KerkRestAdapter.class)
#XmlElement
#HippoEssentialsGenerated(internalName = "gogreen:image")
public Kerk getImage() {
return getLinkedBean("gogreen:image", Kerk.class);
}
}
and my Content rewriter is :
public class RestContentRewriter extends SimpleContentRewriter {
#Override
protected String rewriteBinaryLink(String binaryLinkSrc, Node node, HstRequestContext requestContext, Mount targetMount) {
return super.rewriteBinaryLink(binaryLinkSrc, node, requestContext, requestContext.getMount("site"));
}
And My Adapter is:
public class KerkRestAdapter extends XmlAdapter<String, HippoHtml> {
#Override
public HippoHtml unmarshal(String representation) throws Exception {
throw new UnsupportedOperationException("Unmarshalling not implemented.");
}
#Override
public String marshal(HippoHtml html) throws Exception {
if (html == null) {
return null;
}
final HstRequestContext context = RequestContextProvider.get();
//final RestContentRewriter contentRewriter = new RestContentRewriter();
final ContentReWriter<String> contentRewriter = new RestContentRewriter();
final String rewrite = contentRewriter.rewrite(html.getContent(), html.getNode(), context, context.getMount("api"));
return "<![CDATA[" + rewrite + "]]>";
}
}
additional Question: what is the mount point to be used in rewriter? ( Rest mount name or gogreen??)
Please help !
You have used the Essentials Rest setup tool. That generates a example or demo Rest implementation. After generating the setup a developer shall always want to extend and refine the result.
The links inside rich text in this setup are by default generated for the current mount, which is the rest mount. Since the images are not available through the rest mount, HST generated the /pagenotfound URL.
If you inspect the bean for the Banner you see that for the HippoHtml field an HippoHtmlAdapter is used. Check the code of it: it uses the SimpleContentRewriter. Create your own version of the Adapter and use an extended version of the ContentRewriter. Override the #rewriteBinaryLink method. In it call the super method, but specify the site mount as the target mount.
I think adding an hst:alias to the site mount is a good idea so you can reference the site with the alias.

Using base View Model Class with GalaSoft MVVM Light

I am creating a project using WPF and MVVM-Light library from GalaSoft. I will have a base abstract View Model class, which will be used by all other View Model classes implemented. There I will have MVVM-Light base class as my base class. However, inside this base class, when I try to use RaisePropertyChanged function I get the following error:
An object reference is required for the non-static field, method, or property 'GalaSoft.MvvmLight.ViewModelBase.RaisePropertyChanged(string)'
The code will look like this:
AnalysisViewModelBase : ViewModelBase
{
public const string TagDescriptionStringListPropertyName = "TagDescriptionStringList";
protected static List<string> m_tagDescriptionStringList;
public static List<string> TagDescriptionStringList
{
get
{ return m_tagDescriptionStringList; }
set
{
if (m_tagDescriptionStringList == value)
return;
m_tagDescriptionStringList = value;
RaisePropertyChanged(TagDescriptionStringListPropertyName);
}
}
protected AnalysisViewModelBase()
{
m_tagDescriptionStringList = new List<string>();
m_tagDescriptionStringList.AddRange(new string[] { "North Position", "East Position", "Depth" });
}
}
AnotherViewModel : AnalysisViewModelBase
{ ... }
Could anyone please help me understand what is wrong with my RaiseProperyChanged function?
You are trying to access a Non Static Method From a Static Method... It does not have access to this value, you have to make your method non static.
here is a web page which explains about static methods if you want to have a better understanding of why you can't do what you are trying to do.
Link
You simply must declare your property "Tax DescriptionStringList " as non static. Since the backingfield (m_tagDescriptionStringList) is static it remains the same thing. Make this :
class AnalysisViewModelBase : ViewModelBase
{
public const string TagDescriptionStringListPropertyName = "TagDescriptionStringList";
protected static List<string> m_tagDescriptionStringList;
public List<string> TagDescriptionStringList
{
get
{ return m_tagDescriptionStringList; }
set
{
if (m_tagDescriptionStringList == value)
return;
m_tagDescriptionStringList = value;
RaisePropertyChanged(TagDescriptionStringListPropertyName);
}
}
protected AnalysisViewModelBase()
{
m_tagDescriptionStringList = new List<string>();
m_tagDescriptionStringList.AddRange(new string[] { "North Position", "East Position", "Depth" });
}
}
AnotherViewModel : AnalysisViewModelBase
{ ... }
If it is absolutely necessary to keep the property as a static property in this case, here is a solution: raise the property changes (using RaisePropertyChanged("TagDescriptionStringList")) when it happens, as I indicated in the code below
class AnalysisViewModelBase : ViewModelBase
{
public const string TagDescriptionStringListPropertyName = "TagDescriptionStringList";
protected static List<string> m_tagDescriptionStringList;
public static List<string> TagDescriptionStringList
{
get
{ return m_tagDescriptionStringList; }
set
{
if (m_tagDescriptionStringList != value)
{
m_tagDescriptionStringList = value;
}
}
}
protected AnalysisViewModelBase()
{
m_tagDescriptionStringList = new List<string>();
m_tagDescriptionStringList.AddRange(new string[] { "North Position", "East Position", "Depth" });
RaisePropertyChanged("TagDescriptionStringList");
}
}
AnotherViewModel : AnalysisViewModelBase
{ ... }