|
You can do it (creating a person class then a keycard class inheriting from person class), that is not hard at all. Give it a try. For serialization, you just have to mark both classes with Serializable attribute. Schematically:
[Serializable]
public class Person
{
}
[Serializable]
public class KeyCard : Person
{
}
Regarding the serialization format, you could use a XmlFormatter instead of a BinaryFormatter . Or a XmlSerializer which allows to customize the formatting process even further. Finally, you could also opt in for a JSON serialization.
Showing a binary output in a web application would not be very usefull: do you know anyone willing to read binary format and make sense out of it?
Cheers.
"Five fruits and vegetables a day? What a joke!
Personally, after the third watermelon, I'm full."
|
|
|
|
|
Yeah, that is also how I thought I should do it.
But I am getting a ton of errors when doing so.
"Person does not contain a constructor that takes 0 arguements"
"mykey does not exist within current context"
"method must have a return type"
This is how I wrote it
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Keycard
{
[Serializable()]
public class Person : ISerializable
{
protected string name;
public Person(string name)
{
this.Name = name;
}
public string Name
{
get { return name; }
set { name = value; }
}
[Serializable()]
public class Keycard : Person
{
protected int mykey;
public Keycard(int mykey)
{
this.Mykey = mykey;
}
public int Mykey
{
get { return mykey; }
set { mykey = value; }
}
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", name);
info.AddValue("Keynumber", mykey);
}
public Person(SerializationInfo info, StreamingContext context)
{
Name = (string)info.GetValue("Name", typeof(string));
}
public Keycard(SerializationInfo info, StreamingContext context)
{
Mykey = (int)info.GetValue("Keynumber", typeof(int));
}
public override string ToString()
{
return "Name: " + name + " ---- " + " Keynumber: " + mykey;
}
}
}
|
|
|
|
|
Marc Hede wrote: "Person does not contain a constructor that takes 0 arguements" The Person class has a single constructor accepting a string value as argument. Defining a constructor also means that the class does not have any default parameterless constructor. Since the KeyCard class inherits from Person , it has to provide its base class a name argument (so that the base class can be constructed).
There are several solutions to this:
- you can define a parameterless constructor in the base class.
- you can delete defined constructor in base class (so that compiler generate a default, parameterless one); but this "solution" is not really clever.
- you can provide a default
name argument in KeyCard 's constructor.
In clear:
#region Solution 1 : Defining a parameterless constructor
public class Person
{
public Person() : this("unnamed") { }
}
#endregion
#region Solution 3 : providing a default name in inherited classs' constructor
public class KeyCard : Person
{
public KeyCard(int mykey) : base("unnamed")
{
}
public KeyCard(string name) : base(name)
{
this.Mykey = -1;
}
public KeyCard(string name, int mykey) : base(name)
{
this.Mykey = mykey;
}
}
#endregion
Marc Hede wrote: "mykey does not exist within current context" The compiler does not how to differentiate the mykey parameter of the constructor from the protected mykey field. You can either rename one of them, or just define an auto-implemented property and get rid of the protected field:
public int Mykey { get; set; }
Marc Hede wrote: "method must have a return type" Probably because you defined the KeyCard class inside the Person class, and then defined a KeyCard constructor inside Person (which is incorrect). Please get the KeyCard class out of the Person (you do not need to nest inheriting classes), and put constructors and methods in the class to which they properly belong.
Good work
"Five fruits and vegetables a day? What a joke!
Personally, after the third watermelon, I'm full."
modified 13-Dec-19 5:32am.
|
|
|
|
|
Hey Phil.
Thanks a lot
I almost got it to work. Only one error left thankfully.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Keycard
{
[Serializable()]
public class Person : ISerializable
{
protected string name;
public Person(string name)
{
this.Name = name;
}
public string Name
{
get { return name; }
set { name = value; }
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", name);
}
public Person(SerializationInfo info, StreamingContext context)
{
Name = (string)info.GetValue("Name", typeof(string));
}
}
[Serializable()]
public class Keycard : Person
{
protected int mykey;
public Keycard(string name)
: base (name)
{
this.Mykey = -1;
}
public Keycard(string name, int mykey) : base(name)
{
this.Mykey = mykey;
}
public int Mykey
{
get { return mykey; }
set { mykey = value; }
}
public new void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Keynumber", mykey);
}
public Keycard(SerializationInfo info, StreamingContext context)
{
Mykey = (int)info.GetValue("Keynumber", typeof(int));
}
public override string ToString()
{
return "Name: " + name + " ---- " + " Keynumber: " + mykey;
}
}
}
The only problem here is this line
public Keycard(SerializationInfo info, StreamingContext context)
I get the constructor error again.
I understood your solution with the default name arguement, but how do I apply that logic here?
|
|
|
|
|
public Keycard(SerializationInfo info, StreamingContext context)
: base ("unnamed")
{
Mykey = (int)info.GetValue("Keynumber", typeof(int));
}
|
|
|
|
|
Ah of course.
Sometimes it surprises me how simple the solution is. I tend to overthink things
The only issue now is that I get a
System.Runtime.Serialization.SerializationException
at
Mykey = (int)info.GetValue("Keynumber", typeof(int));
Do I need to add Keynumber in my other class file?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Keycard
{
class Class1
{
public static void Main(string[] args)
{
Keycard k1 = new Keycard("John", 123);
Stream stream = File.Open("KeycardData.dat",
FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, k1);
stream.Close();
k1 = null;
stream = File.Open("KeycardData.dat", FileMode.Open);
bf = new BinaryFormatter();
k1 = (Keycard)bf.Deserialize(stream);
stream.Close();
Console.WriteLine(k1.ToString());
Console.ReadLine();
}
}
}
|
|
|
|
|
Technically, you do not need to provide any customized serialization code for an integer member variable; the Serializable attribute on its own will do just fine.
"Five fruits and vegetables a day? What a joke!
Personally, after the third watermelon, I'm full."
|
|
|
|
|
Ok, I understands what you're doing a bit better now. The GetObjectData method on Person is
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", name);
}
and on Keycard it is
public new void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Keynumber", mykey);
}
The base class (Person) is a normal method and the inherited class (Keycard) is marked "new" which means you're breaking the inheritance chain and saying that the two methods may have the same name but they are their own thing. When you serialise your data as Person is the class that is ISerializable that is the class your GetObjectData is called on, the version on Keycard is never called. What you need to do is mark the version on Person as virtual and the one on Keycard as override. That means that even though GetObjectData is being called on Person, the method on Keycard will be called instead as that version overrides the one on Person. Now your keycard version is being called you can then call the version on Person yourself.
Person;
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", name);
}
Keycard;
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("Keynumber", mykey);
}
Now when serialisation happens both GetObjectData methods will be called.
Your next problem is that when you deserialise Keycard the constructor called is
public Keycard(SerializationInfo info, StreamingContext context)
: base ("unnamed")
{
Mykey = (int)info.GetValue("Keynumber", typeof(int));
}
The problem here (admittedly I did say to code that but I didn't fully understand what you're trying to do) is that your Keycard constructor is called the non-ISerializable constructor on Person;
public Person(string name)
{
this.Name = name;
}
So the keycard constructor is reading the Mykey value from the SerializationInfo object, but the Person constructor is hard-coding the name to "unnamed", it isn't reading from SerializationInfo. So you need to call the ISerializable constructor on Person instead;
public Keycard(SerializationInfo info, StreamingContext context)
: base (info, context)
{
Mykey = (int)info.GetValue("Keynumber", typeof(int));
}
Now both the Keycard and Person parts of your object will initialise themselves from the serialization info.
|
|
|
|
|
Make Person.GetObjectData a virtual method. Change Keycard.GetObjectData to override the method instead of shadowing the method, and have it call the base method.
[Serializable()]
public class Person : ISerializable
{
...
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", name);
}
...
}
[Serializable()]
public class Keycard : Person
{
...
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("Keynumber", mykey);
}
...
} Your code will now work.
However, you're creating Stream objects, which should be disposed of when you're finished with them. The simplest way to do that is with a using block[^].
Keycard k1 = new Keycard("John", 123);
BinaryFormatter bf = new BinaryFormatter();
using (Stream stream = File.Open("KeycardData.dat", FileMode.Create))
{
bf.Serialize(stream, k1);
}
k1 = null;
using (Stream stream = File.Open("KeycardData.dat", FileMode.Open))
{
k1 = (Keycard)bf.Deserialize(stream);
}
Console.WriteLine(k1);
Console.ReadLine();
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Inheriting Keycard from Person really makes no sense. A Keycard is a piece of plastic at best, not a human being.
|
|
|
|
|
I know, but it is a requirement for a project I am making at my university.
My teacher has told me to find help to solve these problems online, and that is why I am here.
It was also his requirement to put binary code on a web page, and I still think it sounds illogical. But upon reading your comments, I am happy that I am not the only one who thinks this way.
I have spent 2 weeks now trying to put binary code inside a web page, and I thought it was me who had overlooked something...
Anyway, I just need help fixing the System.Runtime.Serialization.SerializationException error (the one I mention in the previous post), and then I hopefully won't have to ask for anymore help.
I know as programmers it must be annoying having to create solutions that do not make sense
modified 13-Dec-19 6:42am.
|
|
|
|
|
Marc Hede wrote: It was also his requirement to put binary code on a web page I think you need to ask him to explain what that means. As it stands it means nothing.
|
|
|
|
|
I want to create histogram with Machine names on X axis and observations on Y axis using canvas.js.
Thanks.
|
|
|
|
|
I want to create a time machine.
|
|
|
|
|
That's simple:
Step 1: Go back in time and give yourself the plans to build a time machine.
Step 0: Build the time machine.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
There you will find plenty of samples:
canvasJS Code Samples[^]
We cannot really help you because:- you did not ask any question (you just stated what is your requirement without further information);
- we don't know the data you are dealing with.
"Five fruits and vegetables a day? What a joke!
Personally, after the third watermelon, I'm full."
|
|
|
|
|
I have been trying to experiment with XML and Binary files.
I did so by re-writing a code I made in an ASP NET Web Application.
Keycard.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace Keycard
{
[Serializable()]
public class Keycard : ISerializable
{
protected string name;
protected int mykey;
public Keycard(string name, int mykey)
{
this.Name = name;
this.Mykey = mykey;
}
public string Name
{
get { return name; }
set { name = value; }
}
public int Mykey
{
get { return mykey; }
set { mykey = value; }
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", name);
info.AddValue("Keynumber", mykey);
}
public Keycard(SerializationInfo info, StreamingContext context)
{
Name = (string)info.GetValue("Name", typeof(string));
Mykey = (int)info.GetValue("Keynumber", typeof(int));
}
public override string ToString()
{
return "Name: " + name + " ---- " + " Keynumber: " + mykey;
}
}
}
index.aspx.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Keycard
{
public partial class Index : System.Web.UI.Page
{
public void Main(string[] args)
{
Keycard d1 = new Keycard("John", 102030);
Stream stream = File.Open("KeycardData.dat",
FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, d1);
stream.Close();
d1 = null;
stream = File.Open("KeycardData.dat", FileMode.Open);
bf = new BinaryFormatter();
d1 = (Keycard)bf.Deserialize(stream);
stream.Close();
Console.WriteLine(d1.ToString());
XmlSerializer serializer = new XmlSerializer(typeof(Keycard));
using(TextWriter tw = new StreamWriter(@"L\C#\keycards.xml"))
{
serializer.Serialize(tw, d1);
}
d1 = null;
XmlSerializer deserializer = new XmlSerializer(typeof(Keycard));
TextReader reader = new StreamReader(@"L\C#\keycards.xml");
object obj = deserializer.Deserialize(reader);
d1 = (Keycard)obj;
reader.Close();
Console.WriteLine(d1.ToString());
}
}
}
I am not getting any error messages at all, and when I press IIS Express, I get my index page, which just has a listbox, but of course there is no data in that listbox.
I can not get any data output, and it does not save any XML file in the folder that I specified. I think the reason might be that I am trying to use this code in a Web Application, but I have never worked with any other types of projects, so I am not sure what I should use instead.
Do you guys think this is the reason? Or could there be another reason as to why I am not getting my data to show up?
As I said, I am getting new error messages, so I have no idea where the problem comes from.
|
|
|
|
|
It looks like you are trying to run a Console application inside a web page, which will never work. Create a simple Console application and things should work out for you. You can also step through your code with the debugger in order to examine the variables at each step.
|
|
|
|
|
Thanks.
I got the binary working.
With XML I get an error "cannot be serialized because it does not have a parameterless constructor" at this part:
XmlSerializer serializer = new XmlSerializer(typeof(Keycard));
Not sure what to change/add.
This is how the code looks now after creating it inside a console application.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Keycard
{
class Class1
{
public static void Main(string[] args)
{
Keycard d1 = new Keycard("John", 102030);
Stream stream = File.Open("KeycardData.dat",
FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(stream, d1);
stream.Close();
d1 = null;
stream = File.Open("KeycardData.dat", FileMode.Open);
bf = new BinaryFormatter();
d1 = (Keycard)bf.Deserialize(stream);
stream.Close();
Console.WriteLine(d1.ToString());
XmlSerializer serializer = new XmlSerializer(typeof(Keycard));
using (TextWriter tw = new StreamWriter(@"C\Brugere\Marc8\source\repos\keycards.xml"))
{
serializer.Serialize(tw, d1);
}
d1 = null;
XmlSerializer deserializer = new XmlSerializer(typeof(Keycard));
TextReader reader = new StreamReader(@"C\Brugere\Marc8\source\repos\keycards.xml");
object obj = deserializer.Deserialize(reader);
d1 = (Keycard)obj;
reader.Close();
Console.WriteLine(d1.ToString());
}
}
}
|
|
|
|
|
You need to add the parameterless constructor to your Keycard class as directed by the error message:
public Keycard()
{
this.Name = null;
this.Mykey = null;
}
|
|
|
|
|
I'm looking for an article or sample project that secures a web site, both API and client using .net core 3 and razor pages. The example should NOT be using EntityFramework.
Almost every article/sample I have found is either using EF or is based on core 2.2, I have a folder full of samples where I have downloaded the code, checked the packages and abandoned the project because EF is in there.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
For the clarity...
If you've got .net core 2.2 sample project without EF, what's the problem to refer to .net core 3.0? There's not much changes for ASP.NET projects: What's new in .NET Core 3.0 | Microsoft Docs
Quote: One of the biggest enhancements is support for Windows desktop applications (Windows only). By using the .NET Core 3.0 SDK component Windows Desktop, you can port your Windows Forms and Windows Presentation Foundation (WPF) applications.
|
|
|
|
|
It is an ASP.NeT core razor pages solution. I have three projects in my solution "OdeToFood"
1. OdeToFood (Original Project)
2. OdeToFood.Data (.Net Core Class Library)
3. OdeToFood.Core (.Net Core Class Library)
In OdeToFood.Core, when I use the following using directive in a class in OdeToFood.Core:
using OdeToFood.Data
it works perfect.
Similarly, when I use the following in a class file in OdeToFood.Data
using OdeToFood.Core
it works perfect.
But if I go to the startup.cs file in the "OdeToFood" Project and use
using OdeToFood.Data
It gives an error: The Type or namespace 'Core' does not exist in the namespace "OdeToFood." (Are you missing an assembly reference?)
|
|
|
|
|
Please clarify the references for each project.
Technically, you should reference both Core and Data projects in your main project.
"Five fruits and vegetables a day? What a joke!
Personally, after the third watermelon, I'm full."
|
|
|
|
|
It sounds like you have a circular reference - OTF.Core depends on OTF.Data , and OTF.Data depends on OTF.Core .
You should refactor your code to remove that cycle from your dependency graph.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|