Even using an example from the Documentation, I still can't find a way to successfully serialize to a file.
Code:
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.IO;
using System.Threading;
namespace TestProject
{
class Program
{
static void Main(string[] args)
{
Item i = new Item
{
Username = "user",
Email = "user#user.com",
Password = "password"
};
File.WriteAllText(#"C:\users\user1.json", JsonConvert.SerializeObject(i));
using (StreamWriter file = File.CreateText(#"C:\users\user1.json"))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(file, i);
}
}
}
}
Item.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestProject
{
public class Item
{
public string Email { get; set; }
public string Password { get; set; }
public string Username { get; set; }
}
}
When I run Program.cs, it shows no errors, but the JSON does not show in the file.
When I run your code I get a an exception writing to the users folder. Changing to my home folder works fine. I suspect this is your problem.
Addtionally, you're writing the file twice. The first time is showing an example of using the SerializeObject method to get a string back which is used with WriteAllText. The second block of code is using a StreamWriter. For your purposes, both are equivalent and you only need to use one or the other.
using (StreamWriter file = File.CreateText(#"C:\users\user1.json"))
{
var jsonResult = JsonConvert.SerializeObject(i);
file.WriteLine(jsonResult);
}
Related
I'm learning about WCF, and made a C# fiddle of custom class in the interface that has its own GetEnumerator() method to customize the class' foreach behaviour. The class is as shown:
ProductClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace ProductInterfaces
{
public class ProductData : IEnumerable
{
public string Name { get; set; }
public string ProductNumber { get; set; }
public string Color { get; set; }
public double ListPrice { get; set; }
List<string> myData = new List<string>(new string[] { "test1", "test2", "test3", "test4" });
public IEnumerator<string> GetEnumerator()
{
foreach(string val in myData)
{
yield return val;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
And the contract is as shown (IWCFProductService.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace ProductInterfaces
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IWCFProductService" in both code and config file together.
[ServiceContract]
public interface IWCFProductService
{
[OperationContract]
ProductData GetProduct(string productNumber);
}
}
The implementation of the GetProduct() method is as shown:
using ProductInterfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace ProductService
{
public class WCFProductService : IWCFProductService
{
public ProductData GetProduct(string productNumber)
{
using (adventureworksEntities database = new adventureworksEntities())
{
var table_of_products = database.products;
ProductData desired_product = new ProductData();
foreach (var p in table_of_products)
{
if (p.ProductNumber == productNumber)
{
Console.WriteLine("Test using a custom foreach of ProductData class");
foreach (string i in desired_product)
{
Console.WriteLine(i);
}
desired_product.Name = p.Name;
desired_product.ProductNumber = p.ProductNumber;
desired_product.Color = p.Color;
desired_product.ListPrice = p.ListPrice;
return desired_product;
}
}
throw new Exception();
}
}
}
}
When called by the client:
using ProductInterfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace ProductClient
{
class Program
{
static void Main(string[] args)
{
// Client creates channel factory by passing in the name of the endpoint (i.e. ProductServiceEndpoint)
ChannelFactory<IWCFProductService> channelFactory = new ChannelFactory<IWCFProductService>("ProductServiceEndpoint");
// Create a proxy i.e. create a channel
IWCFProductService proxy = channelFactory.CreateChannel();
Console.WriteLine("Input product name to be searched:");
string input = Console.ReadLine();
var searchResult = proxy.GetProduct(input);
Console.WriteLine(searchResult.Name);
Console.ReadLine();
}
}
}
It fails at var searchResult = proxy.GetProduct(input);, with exception saying
System.ServiceModel.CommunicationException: 'An error occurred while receiving the HTTP response to http://localhost:9999/ProductService. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.'
I did some trial and error, and if I remove IEnumerable and the foreach loop, there is no issue and searchResult is a valid object. Why is this happening? Am I understanding something wrong?
I think it should be a serialization issue, WCF needs to have concrete classes to pass data.
It cannot return IEnumerable - try using List (or T[] array) or concrete types.
You can also use the Service Trace Viewer to find specific issues.
Posts with similar questions
WCF Web Service error: "Service endpoint binding not using HTTP protocol"?
This could be due to the service endpoint binding not using the HTTP protocol
i am trying to make an angular application that takes an api made from asp.net core but while making the api , it didn't work and appear as planned and didn't know where was the problem...
I made an asp.net core web app.
This is the student.cs file made in the model folder
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI101.Model
{
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public bool Pass { get; set; }
}
}
This is the studentmanager also in model folder
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI101.Model
{
public class StudentManager
{
public List<Student> GetResults()
{
List<Student> oList = new List<Student>();
var r = new Random();
for(int i = 0; i < 10; i++)
{
var x = new Student();
x.ID = i;
x.Name = String.Format("Name{0}", i, ToString());
x.Pass = (r.Next() % 2 == 0);
oList.Add(x);
}
return oList;
}
}
}
This is the code that should return aaaaa
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebAPI101.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class StudentController : ControllerBase
{
[Route("mariam")]
public string test()
{
return "aaaaa";
}
}
}
I tried to launch the code and it didn't work as planned o the link:https://localhost:5001/api/Student/mariam
The problem is you are using [Route("mariam")] which overrides the controller route.
You need to use [HttpGet("mariam")] instead.
[HttpGet("mariam")]
public string test()
{
return "aaaaa";
}
Using HttpGet will add to the controller route.
This question already has answers here:
Append lines to a file using a StreamWriter
(11 answers)
Closed 1 year ago.
I need to create a method called publish, to get the name, description, endpoint, no of operands and operand type in JSON format and write it to a text file. I have implemented that part but after the first API call the text in the text file is getting over written which is not what I want. I have included the model class and the controller class below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Registry.Models
{
public class publishModel
{
public string Name { get; set; }
public string Description { get; set; }
public string endpoint { get; set; }
public int NoOfoperands { get; set; }
public string operandType { get; set; }
}
}
using Newtonsoft.Json;
using Registry.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Web.Http;
namespace Registry.Controllers
{
public class publishController : ApiController
{
[Route("api/publish")]
[HttpPost]
public string publish(publishModel pModel)
{
string servicePath = #"C:\Users\ASUS\source\repos\DC assignment 1\Services.txt";
MemoryStream ms = new MemoryStream();
var write = new Utf8JsonWriter(ms);
write.WriteStartObject();
write.WriteString("Name", pModel.Name);
write.WriteString("Description", pModel.Description);
write.WriteString("Endpoint", pModel.endpoint);
write.WriteString("No of operands", pModel.NoOfoperands.ToString());
write.WriteString("Operand type", pModel.operandType);
write.WriteEndObject();
write.Flush();
string json = Encoding.UTF8.GetString(ms.ToArray());
//string json = JsonConvert.SerializeObject(pModel);
try
{
using (StreamWriter writer = new StreamWriter(servicePath))
{
writer.Write(json);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return "Description saved";
}
}
}
https://learn.microsoft.com/en-us/dotnet/api/system.io.streamwriter.-ctor?view=net-5.0#System_IO_StreamWriter__ctor_System_String_System_Boolean_
Add an extra argument to your StreamWriter:
using (StreamWriter writer = new StreamWriter(servicePath, true))
That tells it you open the path for writing, but append to the file. When you don't pass in a Boolean (which is what you are doing) it defaults to overwriting the file.
I already create new custom field for screen Fixed Asset. The following code is my DAC extension:
using PX.Data;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.EP;
using PX.Objects.FA;
using PX.Objects.GL;
using PX.Objects;
using System.Collections.Generic;
using System;
namespace SGLCustomizeProject
{
public class FALocationHistoryExtension : PXCacheExtension<PX.Objects.FA.FALocationHistory>
{
#region UsrKodeArea
[PXDBString(50)]
[PXUIField(DisplayName = "Kode Area")]
[PXSelector(typeof(Search<KodeAreaMaster.roomCD,
Where<KodeAreaMaster.status,
Equal<statusActive>,
And<KodeAreaMaster.buildingID,
Equal<Current<FALocationHistory.buildingID>>>>>),
typeof(KodeAreaMaster.roomCD),
typeof(KodeAreaMaster.roomDescription),
typeof(KodeAreaMaster.buildingID),
typeof(KodeAreaMaster.status))]
public virtual string UsrKodeArea { get; set; }
public abstract class usrKodeArea : IBqlField { }
#endregion
#region UsrDeskripsiArea
[PXDBString(75)]
[PXUIField(DisplayName = "Deskripsi Area")]
public virtual string UsrDeskripsiArea { get; set; }
public abstract class usrDeskripsiArea : IBqlField { }
#endregion
}
}
I need to fill the selected value into another additional field in the current screen, please see the following screenshot:
I need to fill value of Deskripsi Area from selector field (pop up) into Deskripsi Area field.
I have tried the following code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Common;
using PX.Data;
using PX.Objects.CS;
using PX.Objects.CR;
using PX.Objects.CM;
using PX.Objects.GL;
using PX.Objects.AP;
using PX.Objects.EP;
using PX.Objects.IN;
using PX.Objects.FA.Overrides.AssetProcess;
using PX.Objects;
using PX.Objects.FA;
namespace SGLCustomizeProject
{
public class AssetMaint_Extension : PXGraphExtension<AssetMaint>
{
public virtual void _(Events.FieldUpdated<FALocationHistory, FALocationHistoryExtension.usrKodeArea> e)
{
var row = e.Row;
var ext = row.GetExtension<FALocationHistoryExtension>();
e.Cache.SetValue<FALocationHistoryExtension.usrDeskripsiArea>(row, ext.UsrKodeArea);
}
}
}
This code above has been worked, but the result is when I choose Kode Area field, it also fill into Deskripsi Area field. My goal is to fill Deskripsi Area with the same field (Deskripsi Area) from selector field.
I tried to change code above with the following code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Common;
using PX.Data;
using PX.Objects.CS;
using PX.Objects.CR;
using PX.Objects.CM;
using PX.Objects.GL;
using PX.Objects.AP;
using PX.Objects.EP;
using PX.Objects.IN;
using PX.Objects.FA.Overrides.AssetProcess;
using PX.Objects;
using PX.Objects.FA;
namespace SGLCustomizeProject
{
public class AssetMaint_Extension : PXGraphExtension<AssetMaint>
{
public virtual void _(Events.FieldUpdated<FALocationHistory, FALocationHistoryExtension.usrKodeArea> e)
{
var row = e.Row;
var ext = row.GetExtension<FALocationHistoryExtension>();
e.Cache.SetValue<FALocationHistoryExtension.usrDeskripsiArea>(row, ext.UsrDeskripsiArea);
}
}
}
But it doesn't work. Any step that I forget ?
Change the ALocationHistoryExtension_UsrKodeArea_FieldUpdated to ALocationHistory_UsrKodeArea_FieldUpdated
protected virtual void FALocationHistory_UsrKodeArea_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
if (e.Row is FALocationHistory)
{
sender.SetDefaultExt<FALocationHistoryExtension.usrDeskripsiArea>(e.Row);
}
}
To Override an Event Handler
use xxx_fieldUpdated event
In your aspx page check, that you have commitchanges set to true
[ as usually optional ] sometime is necessary to set autorefresh = true
Starting from 2017 R2 you can also use this approach:
public virtual void _(Events.FieldUpdated<FALocationHistory, FALocationHistoryExtension.usrKodeArea> e)
{
var row = e.Row;
var ext = row.GetExtension<FALocationHistoryExtension>();
e.Cache.SetValue<FALocationHistoryExtension.usrDeskripsiArea>(row, ext.UsrKodeArea);
var KodeAreaMaster =
PXSelect<KodeAreaMaster, Where<KodeAreaMaster.roomCD, Equal<Required<KodeAreaMaster.roomCD>>>>
.Select(Base, ext.UsrKodeArea).First().GetItem<KodeAreaMaster>();
e.Cache.SetValueExt<FALocationHistoryExtension.usrDeskripsiArea>();
}
I used the following code to provide my goal. Thanks for everyone for all the respons. :)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Common;
using PX.Data;
using PX.Objects.CS;
using PX.Objects.CR;
using PX.Objects.CM;
using PX.Objects.GL;
using PX.Objects.AP;
using PX.Objects.EP;
using PX.Objects.IN;
using PX.Objects.FA.Overrides.AssetProcess;
using PX.Objects;
using PX.Objects.FA;
namespace SGLCustomizeProject
{
public class AssetMaint_Extension : PXGraphExtension<AssetMaint>
{
public virtual void _(Events.FieldUpdated<FALocationHistory, FALocationHistoryExtension.usrKodeArea> e)
{
var row = e.Row;
var ext = row.GetExtension<FALocationHistoryExtension>();
if (ext.UsrKodeArea != null)
{
e.Cache.SetValue<FALocationHistoryExtension.usrDeskripsiArea>(row, ext.UsrKodeArea);
var kodeAreaMaster = PXSelect<KodeAreaMaster,
Where<KodeAreaMaster.roomCD,
Equal<Required<KodeAreaMaster.roomCD>>>>
.Select(Base, ext.UsrKodeArea).First().GetItem<KodeAreaMaster>();
e.Cache.SetValueExt<FALocationHistoryExtension.usrDeskripsiArea>(row, kodeAreaMaster.RoomDescription);
}
}
public virtual void _(Events.FieldUpdated<FALocationHistory.buildingID> e)
{
var row = e.Row as FALocationHistory;
var ext = row.GetExtension<FALocationHistoryExtension>();
if (row.BuildingID != null)
{
if (ext.UsrKodeArea != null)
{
var kodeAreaMaster = PXSelect<KodeAreaMaster,
Where<KodeAreaMaster.roomCD,
Equal<Required<KodeAreaMaster.roomCD>>>>
.Select(Base, ext.UsrKodeArea).First().GetItem<KodeAreaMaster>();
if (row.BuildingID == kodeAreaMaster.BuildingID)
{
return;
}
else
{
e.Cache.SetValueExt<FALocationHistoryExtension.usrKodeArea>(row, null);
e.Cache.SetValueExt<FALocationHistoryExtension.usrDeskripsiArea>(row, null);
}
}
}
else
{
e.Cache.SetValueExt<FALocationHistoryExtension.usrKodeArea>(row, null);
e.Cache.SetValueExt<FALocationHistoryExtension.usrDeskripsiArea>(row, null);
}
}
}
}
I want to add a custom Attribute belonging to a field
Goal is to get the following XML:
<?xml version="1.0"?>
<doc>
<assembly>
<name>class1</name>
</assembly>
<members>
<member name="P:class1.clsPerson.isAlive">
<Element>
isAlive
</Element>
<Description>
Whether the object is alive or dead
</Description>
<StandardValue>
false
</StandardValue>
</member>
</members>
</doc>
What I currently have:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace class1
{
public class clsPerson
{
[XmlElement(ElementName="isAlive")]
[Description("Whether the object is alive or dead")]
[StandardValue(false)]
public bool isAlive { get; set; }
}
class Program
{
static void Main(string[] args)
{
clsPerson p = new clsPerson();
p.isAlive = true;
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(p.GetType());
x.Serialize(Console.Out, p);
Console.WriteLine();
Console.ReadLine();
}
}
}
My current Annotation classes:
using System;
namespace class1
{
internal class StandardValueAttribute : Attribute
{
public readonly object DefaultValue;
public StandardValueAttribute(Object defaultValue)
{
this.DefaultValue = defaultValue;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace class1
{
internal class DescriptionAttribute : Attribute
{
private string v;
public DescriptionAttribute(string v)
{
this.v = v;
}
}
}
How can I add my custom Attributes like Description and StandardValue to the XMLSerializer?
It looks like you want to reinvent the wheel. if you trying to export a code documentation I suggest you using the built in functionality:
https://msdn.microsoft.com/en-us/library/b2s063f7.aspx
The XML documentation files are then generated and you can even use them in intellisense
The XMLSerializer will just store the content of an instance.
Using xml Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication14
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
string name = "P:class1.clsPerson.isAlive";
XElement person = doc.Descendants("member").Where(x => (string)x.Attribute("name") == name).FirstOrDefault();
person.Add(new object[] {
new XElement("Description", "Whether the object is alive or dead"),
new XElement("StandardValue", false)
});
}
}
}