I am making an app of drinks for windows store.
According to requirement user can select drink as favorite.
So his favorite drinks should be shown in favorite page.
So how can I add these drinks to favorite page on button click as shown in image 1
Is it possible without using database..?
Any share of idea would be appreciated.
I am using xml file to save data on button click
I have managed to get the data from xml file in a grid on my favourite page
but it is statically done by me as I had wrote xml file by myself.
I want it to be wrote like that:
<drink>
<drinkImage>ck.png</drinkImage>
<drinkTitle>COKE</drinkTitle>
<drinkDescription>(1793-1844)</drinkDescription>
</drink>
my current file is this:
<?xml version="1.0" encoding="utf-8" ?>
<drinks>
<drink>
<drinkImage>pepsi.png</drinkImage>
<drinkTitle>PEPSI</drinkTitle>
<drinkDescription>(1793-1844)</drinkDescription>
</drink>
**<here I Want above xml on add to my favourite button click>**
</drinks>
The solution you're looking for really depends on what it is that you're wanting to get out of the adding to favourites page.
If you just want to add it to the favourites page for the duration of the app, have a ViewModel which contains the collection of favourites that you can access from any page by storing it in an IOC container (possibly using MVVMLight).
If you're wanting to then save it, you can write the favourites out to a JSON file which you can store in the local storage for the application. You'll also want to load it back into your app next time it loads.
You can do your JSON save logic as below
/// <summary>
/// Save an object of a given type as JSON to a file in the storage folder with the specified name.
/// </summary>
/// <typeparam name="T">The type of object</typeparam>
/// <param name="folder">Folder to store the file in</param>
/// <param name="data">The object to save to the file</param>
/// <param name="encoding">The encoding to save as</param>
/// <param name="fileName">The name given to the saved file</param>
/// <returns>Returns the created file.</returns>
public async Task<StorageFile> SaveAsJsonToStorageFolder<T>(StorageFolder folder, T data, Encoding encoding, string fileName)
{
if (folder == null)
throw new ArgumentNullException("folder");
if (data == null)
throw new ArgumentNullException("data");
if (fileName == null)
throw new ArgumentNullException("fileName");
string json = JsonConvert.SerializeObject(data, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
byte[] bytes = encoding.GetBytes(json);
return await this.SaveBytesToStorageFolder(folder, bytes, fileName);
}
/// <summary>
/// Saves a byte array to a file in the storage folder with the specified name.
/// </summary>
/// <param name="folder">Folder to store the file in</param>
/// <param name="bytes">Bytes to save to file</param>
/// <param name="fileName">Name to assign to the file</param>
/// <returns>Returns the created file.</returns>
public async Task<StorageFile> SaveBytesToStorageFolder(StorageFolder folder, byte[] bytes, string fileName)
{
if (folder == null)
throw new ArgumentNullException("folder");
if (bytes == null)
throw new ArgumentNullException("bytes");
if (string.IsNullOrWhiteSpace(fileName))
throw new ArgumentNullException("fileName");
StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBytesAsync(file, bytes);
return file;
}
Related
Per this Using System.Text.Json to Serialize an IConfiguration back to Json it seems that the limited type information that you can put into JSON is discarded.
You seem to be under the impression that IConfiguration objects are storing ints, bools, etc. (for example) corresponding to the JSON Element type. This is incorrect. All data within an IConfiguration is stored in stringified form. The base Configuration Provider classes all expect an IDictionary<string, string> filled with data. Even the JSON Configuration Providers perform an explicit ToString on the values.
I noticed this when I addressed the problem posed in that question with this extension method.
using System.Collections.Generic;
using System.Dynamic;
using Microsoft.Extensions.Configuration;
public static class ExtendConfig
{
public static dynamic AsDynamic(this IConfigurationRoot cr)
{
var result = new ExpandoObject();
var resultAsDict = result as IDictionary<string, object>;
foreach (var item in cr.AsEnumerable())
{
resultAsDict.Add(item.Key, item.Value);
}
return result;
}
}
This method reconstructs the graph but everything is now a string.
I could write my own parser and apply it to the original JSON string but that's a bit dire. Is there any way I can get this metadata so I can improve the fidelity of merged configs? I'm passing it through for consumption by JS which does notice the difference.
Merging is why I'm using the config extensions builder.
As IConfiguration doesn't provide the information about types, but System.Text.Json used by JsonConfigurationProvider does, the working solution (or a workaround) would be using the System.Text.Json deserializer directly to read the configuration file and match the types to the configuration keys.
But we have some minor issues to solve first. Like - where is the configuration file? We don't want to duplicate that information in code, we have to extract it from IConfiguration instance.
Then - match the concrete existing configuration key to the JSON document tree node. That will require either DFS or BFS tree traversal algorithm. I'll go for DFS (Depth First Search). In a nutshell - if you have expandable nodes, you put them in the stack in reverse order. Then you have a while loop that takes a node from the stack, if it has children, you put them on the same stack, if not - you just yield the node. As simple as that, and BFS is pretty similar, but nevermind.
There's one thing more: Newtonsoft.Json - a popular Nuget package that was at a time used even by Microsoft. That JSON serializer is a little slower than System.Text.Json, but it's more advanced, allowing the user to build a JSON document tree node by node.
Having this powerful tool makes creating a writeable JSON IConfiguration relatively easy, especially using some helpers like mine below.
Look at the SaveChanges() method. It walks through the IConfiguration nodes, matches appropriate JObject nodes by their path and copies the changes from IConfiguration instance to the JObject instance. Then you can just write the JSON file.
There's an ugly hack used to get the file. I get the private field containing the IConfigurationRoot instance, but that could be skipped if you already have the configuration root. Having the root you can get JsonConfigurationProvider from it, then it's just Source.Path property.
So here's the code. It's a part of the Woof.Toolkit and Woof.Config Nuget package, that provides writeable JSON configurations, some helper methods to them, and also Azure Key Vault client that uses a JSON configuration, with some helper methods to encrypt and decrypt sensitive data with keys stored on AKV.
This is the first release of ConfigurationExtensions class, so it might be sub-optimal in performance terms, but it works and illustrates how you can match the IConfiguration instance nodes with JObject nodes to get the types of the configuration properties.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using Newtonsoft.Json.Linq;
namespace Woof.Config;
/// <summary>
/// Extensions for <see cref="IConfiguration"/> making JSON type <see cref="IConfiguration"/> writeable.
/// </summary>
public static class ConfigurationExtensions {
/// <summary>
/// Gets the configuration root element.
/// </summary>
/// <param name="configuration">Any <see cref="IConfiguration"/> part.</param>
/// <returns>Root element.</returns>
public static IConfigurationRoot? GetRoot(this IConfiguration configuration) {
if (configuration is IConfigurationRoot root) return root;
var rootField = configuration.GetType().GetField("_root", BindingFlags.Instance | BindingFlags.NonPublic);
return rootField?.GetValue(configuration) as IConfigurationRoot;
}
/// <summary>
/// Gets the first <see cref="JsonConfigurationProvider"/> if exists, null otherwise.
/// </summary>
/// <param name="root">Configuration root element.</param>
/// <returns><see cref="JsonConfigurationProvider"/> or null.</returns>
public static JsonConfigurationProvider? GetJsonConfigurationProvider(this IConfigurationRoot root)
=> root.Providers.OfType<JsonConfigurationProvider>().FirstOrDefault();
/// <summary>
/// Gets the first <see cref="JsonConfigurationProvider"/> if exists, null otherwise.
/// </summary>
/// <param name="config">Any <see cref="IConfiguration"/> part.</param>
/// <returns><see cref="JsonConfigurationProvider"/> or null.</returns>
public static JsonConfigurationProvider? GetJsonConfigurationProvider(this IConfiguration config)
=> config.GetRoot()?.GetJsonConfigurationProvider();
/// <summary>
/// Saves changes made to <see cref="IConfiguration"/> to the JSON file if exists.
/// </summary>
/// <param name="config">Any <see cref="IConfiguration"/> part.</param>
/// <exception cref="InvalidOperationException">Configuration does not have <see cref="JsonConfigurationProvider"/>.</exception>
public static void SaveChanges(this IConfiguration config) {
var provider = config.GetJsonConfigurationProvider();
if (provider is null) throw new InvalidOperationException("Can't get JsonConfigurationProvider");
var sourceJson = File.ReadAllText(provider.Source.Path);
var target = JObject.Parse(sourceJson);
var stack = new Stack<IConfigurationSection>();
foreach (IConfigurationSection section in config.GetChildren().Reverse()) stack.Push(section);
while (stack.TryPop(out var node)) {
var children = node.GetChildren();
if (children.Any()) foreach (var child in children.Reverse()) stack.Push(child);
else {
var jPath = GetJPath(node.Path);
var element = target.SelectToken(jPath);
var valueString =
element!.Type == JTokenType.Null
? "null" :
element!.Type == JTokenType.String ? $"\"{node.Value}\"" : node.Value;
element!.Replace(JToken.Parse(valueString));
}
}
File.WriteAllText(provider.Source.Path, target.ToString());
}
/// <summary>
/// Sets <paramref name="configuration"/>'s <paramref name="key"/> with specified <paramref name="value"/>.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="key">The key of the configuration section.</param>
/// <param name="value">Value to set.</param>
/// <exception cref="InvalidOperationException">Not supported type as value.</exception>
public static void SetValue(this IConfiguration configuration, string key, object? value) {
var c = CultureInfo.InvariantCulture;
var valueString = value switch {
null => null,
string v => v,
Uri v => v.ToString(),
byte[] v => Convert.ToBase64String(v),
bool v => v.ToString(c),
int v => v.ToString(c),
decimal v => v.ToString(c),
double v => v.ToString(c),
uint v => v.ToString(c),
long v => v.ToString(c),
ulong v => v.ToString(c),
short v => v.ToString(c),
ushort v => v.ToString(c),
byte v => v.ToString(c),
sbyte v => v.ToString(c),
float v => v.ToString(c),
_ => throw new InvalidOperationException($"Cannot set value of type {value.GetType()}")
};
configuration[key] = valueString;
}
/// <summary>
/// Gets the path for JObject.SelectToken method.
/// </summary>
/// <param name="path"><see cref="IConfiguration"/> path.</param>
/// <returns><see cref="JObject"/> path.</returns>
private static string GetJPath(string path) => RxIConfigurationIndex.Replace(path, "[$1]").Replace(':', '.');
/// <summary>
/// Matches the <see cref="IConfiguration"/> indices.
/// </summary>
private static readonly Regex RxIConfigurationIndex = new(#":(\d+)", RegexOptions.Compiled);
}
Why JObject? Can JSON file represent only an object? No - it can represent any value, including null. But the JSON configuration MUST be an object. That's why I use JObject as my secondary configuration root.
I have a this model:
public partial class UserPosition
{
...
public DbGeometry Position { get; set; }
...
}
I create this object and save it to the MySql DB (db is my DBContext):
var pos = new UserPosition
{
...
Position = GeographyHelper.CreatePoint(request.Latitude, request.Longitude),
...
};
db.UserPositions.Add(pos);
db.SaveChanges();
GeographyHelper.CreatePoint:
/// <summary>
/// Creates a DbGeometry point from latitude and longitude values
/// </summary>
/// <param name="latitude"></param>
/// <param name="longitude"></param>
/// <returns></returns>
public static DbGeometry CreatePoint(double latitude, double longitude)
{
var text = string.Format(CultureInfo.InvariantCulture.NumberFormat, "POINT({0} {1})", longitude, latitude);
// 4326 is most common coordinate system used by GPS/Maps
return DbGeometry.PointFromText(text, 4326);
}
The value is perfectly saved to to DB:
POINT (19.038934 47.531)
But when I read the value from the DB, the Position is null, other fields are OK:
var rec = db.UserPositions.FirstOrDefault()
I get the right record because the ID matches.
Why is the Position null?
Visual Studio 2015, .NET 4.5.2, EntityFramework 6.2.0, MySql.Data.Entity.EF6 6.9.12, MySql database version: 5.6.15.
It was globalization problem: decimal point was saved to the DB but couldn't parse the same geometry data when read because decimal comma was needed (for Double.TryParse()) because of the globalization. The fast solution was to set the globalization to en-US in web.config but I accept if you know better solution :)
<configuration>
<system.web>
<globalization uiCulture="en-US" culture="en-US"/>
...
This is my struts.xml file.
<action name="sample" class="com.action.getPdf" method="getPdf">
<result name="success" type="stream">
<param name="inputName">fileInputStream</param>
<param name="contentType">application/pdf</param>
<param name="contentDisposition">attachment;filename="${fileName}"</param>
<param name="bufferSize">1024</param>
</result>
</action>
and this is action code where the object of File is getting null.
public String getPdf()throws Exception
{
Session ss = HibernateUtils.getSess();
Transaction t=ss.beginTransaction();
HttpSession httpsession=request.getSession();
String path2=request.getParameter("path1");
ServletContext servletContext = ServletActionContext.getServletContext();
//String path3=servletContext.getRealPath(path2);
System.out.println("the relative path of the file is:"+path2);
try
{
File fileToDownload = new File(path2);
fileInputStream = new FileInputStream(fileToDownload);
}
catch (Exception e)
{
if (t!=null)
{
t.rollback();
e.printStackTrace();
}
}
finally
{
ss.close();
}
return "success";
}
I have stored the file which I want to download in web content folder and I have stored the path of it in the database.
The problem with
String path2=request.getParameter("path1");
This method may return null if parameter path1 is missing. If it's not null then it should be a valid path to the readable file that you application has access.
Read the example: How to read file in Java – FileInputStream. You can trace the output with the code.
System.out.println("Total file size to read (in bytes) : "
+ getFileInputStream().available());
The getter is needed to return a stream result, and as you are using dynamic parameter in the result config. You should provide the getter for fileName.
I have solved this question. I have stored the physical path of the file in the data base.For example if your project path is :
D:/Workspace_ABC/SampleProject/WebContent/D-Files/APJ.AbdulKalam.pdf
then store this path as it is in the database table. and then use this path to download file.
I'm working on a visualforce project that requires generating csv file from a group of field values.
I'm using the following code to generate csv, I'm supposed to click on a command button to generate the file but the problem is that when i click save on the apex page an empty file is generated without taking the required data.
Visualforce page:
<apex:page controller="test2" contentType="text/csv#{!fileName}.csv" showHeader="false" sidebar="false" standardStylesheets="false">
<apex:form >
<apex:outputText value="{!input}" escape="false"/>
<apex:commandButton action="{!exportContent}"/>
</apex:form>
</apex:page>
Controller:
public with sharing class test2 {
// Controller for ExportData.page,
// which expects to be handed the following POST variables:
// #inputdata(string) data to export (i.e. in CSV format)
// #filename(string) name of the file to export, e.g. 'AccountData'
public transient String input { public get; private set; }
public transient String fileName { public get; private set; }
public void exportContent(){
Map<String,String> params = ApexPages.currentPage().getParameters();
// We expect to be handed POST variables called 'inputdata' and 'filename'
fileName = params.get('filename');
if (fileName == null) fileName = 'Data';
input = params.get('inputdata');
if (input == null) input = 'No data provided.';
}
}
You will be extremely limited in how much data can be passed in the Query String using the PageReference.getParameters() method. Note that this method is limited to URL parameters. POST variables need to be handled by having a common controller class with a non-transient member to deserialize the data into. See PageReference.setRedirect(Boolean)
If set to false, the redirect is a server-side forward that preserves the view state if and only if the target page uses the same controller and contains the proper subset of extensions used by the source page.
I've put together an example of viewing a CSV via Visualforce - Prototype CSV viewer for Visualforce. You may be able to adapt it to your needs.
Incidentally, the Salesforce Stackexchange is a great place to ask Salesforce specific questions.
unfortunately, I was not successful with my research for this topic.
With an anchor tag, I was able to do this:
My Link ®
Now I want the same with an Html.Actionlink:
#Html.ActionLink("My Link ®", "Action")
But the output is the same as the input and not a reg symbol as it is intended.
Any idea?
Thanks in advance!
#Html.ActionLink("My Link ®", "Action")
or
My Link ®
ActionLink always use call of HttpUtility.Encode for the link text.
You can use UrlHelper Method like
My Link ®
You can use an HtmlString (MvcHtmlString in .NET 2 / MVC 2) to indicate that you do not wish it to be re-encoded:
#Html.ActionLink(new HtmlString("My Link ®"), "Action");
Here is how I solved this in MVC 2:
/// <summary>
/// Creates an anchor tag based on the passed in controller type and method.
/// Does NOT encode passed in link text.
/// </summary>
/// <typeparam name="TController">The controller type</typeparam>
/// <param name="htmlHelper">The HTML helper</param>
/// <param name="action">The method to route to</param>
/// <param name="linkText">The linked text to appear on the page</param>
/// <returns>A formatted anchor tag</returns>
public static MvcHtmlString ActionLink<TController>( this HtmlHelper htmlHelper,
Expression<Action<TController>> action,
HtmlString linkText ) where TController : Controller
{
return ActionLink( htmlHelper, action, linkText, null, null );
}
/// <summary>
/// Creates an anchor tag based on the passed in controller type and method.
/// Does NOT encode passed in link text.
/// </summary>
/// <typeparam name="TController">The controller type</typeparam>
/// <param name="htmlHelper">The HTML helper</param>
/// <param name="action">The method to route to</param>
/// <param name="linkText">The linked text to appear on the page</param>
/// <param name="routeValues">The route values</param>
/// <param name="htmlAttributes">The HTML attributes</param>
/// <returns>A formatted anchor tag</returns>
public static MvcHtmlString ActionLink<TController>( this HtmlHelper htmlHelper,
Expression<Action<TController>> action,
HtmlString linkText,
object routeValues,
object htmlAttributes ) where TController : Controller
{
var routingValues = GetRouteValuesFromExpression( action, routeValues );
var url = UrlHelper.GenerateUrl( null, //routeName
null, //actionName
null, //controllerName
routingValues,
htmlHelper.RouteCollection,
htmlHelper.ViewContext.RequestContext,
false ); //includeImplicitMvcValues
var tagBuilder = new TagBuilder("a")
{
InnerHtml = !String.IsNullOrEmpty( linkText.ToString() ) ? linkText.ToString() : String.Empty
};
tagBuilder.MergeAttributes( (IDictionary<string, object>)htmlAttributes );
tagBuilder.MergeAttribute( "href", url );
return MvcHtmlString.Create( tagBuilder.ToString( TagRenderMode.Normal ) );
}
It is strongly typed, as in the MVC futures NuGet package. So you can use it like this:
<%= Html.ActionLink<HomeController>( x => x.Index(),
new HtmlString( "Don't Encode Me!<sup>®</sup>" ) ) %>