Add property to a DeserializeObject instance? - asp.net-core

I am DeserializeObject json to object.
if this is the json:
{
"IsSuccess":true,
"ErrorDescription":"the descriptions"
}
and I do not know the class.
public T Get<T>(string p1)
{
var response=JsonConvert.DeserializeObject<T>(str);
//how to add property to response here?
return response
}
I want to add a property to response but I do not know if response is null or not.
and I do not know which class is it.
I think it can not so:
If there is BaseClass:
public class BaseResp
{
public bool IsSuccessStatus{get;set;}
}
and if T is inherited by BaseResp then can I add property to it?
If I can not add property to it then can I return a new instance of BaseResp ?
public T Get<T>(string p1)
{
var response=JsonConvert.DeserializeObject<T>(str);
if(response==null)
{
return new BaseResp();
}
}

Related

This HttpRequestMessage Headers are assignable even that they are { get; } only

Why do I get about this assignment into Headers this error
var request = new HttpRequestMessage()
{
Headers = default
};
Property or indexer 'property' cannot be assigned to -- it is read only
And it is the same even if i assign null.
And for the following code i dont get it, ain't it also an assignment of value to `Headers` property ?
var request = new HttpRequestMessage()
{
Headers = {}
};
{} is a collection initializer:
int[] fooBar = { };
I cannot find a proof that empty collection initializer {} can be assigned to readonly property which has reference type.
However, this code is valid:
public class FooBar
{
public object MyProperty { get; }
}
var foo = new FooBar()
{
MyProperty = { }
};
After some research it seems that if a property is read-only, items can be added to it using {}, this is the meaning of this operator, this is not an assignment to the property reference. for example:
public class ItemsContainer
{
public List<string> Items { get; } = new List<string> { "a" };
}
This code will producde:
ItemsContainer itemsContainer = new ItemsContainer()
{
Items = { "b" }
};
Console.WriteLine(string.Join(',', itemsContainer.Items));
Will have result of:
a,b
Which mean that it only adds to the collection.
If we change the implimitaitiom of ItemsContainer to:
public class ItemsContainer
{
public List<string> Items { get; }
}
For the same code a NullReferenceException will be thrown because you try to add to a collection which is not initialized and have a null value.
More info:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers#object-initializers-with-collection-read-only-property-initialization
You can't. That is what read-only properties are for. You cannot the change the actual reference, but you can change the value itself. Based on what the concrete type allows.
If you want to have the headers empty (which it looks like from your example), you just use request.Headers.Clear(). And other methods alike if you want to alter/add/etc. headers.

how to make a custom error message with extension method in fluent validation

public class Validator : AbstractValidator<Command>
{
public Validator(ICheckExists<ICheckEntityExists> checkEntityExists)
{
RuleFor(x => x)
.EntityDoesNotExist(checkEntityExists, c => new CheckEntityExists()
{
TypeId = c.Id,
StatusId = c.StatusId
});
}
Hi, I Have a problem. The code above generates "must not exist" error message.
EntityDoesNotExist is an extension method that I can not change.Since it is an extension method I could not use any of this OverridePropertyName WithName WithMessage.
The question is how can I change the error message to a custom one.
I have written this code which does the thing
ValidatorOptions.Global.DisplayNameResolver = (type, member, expression) =>
{
if (member == null)
{
return "Hello world";
}
return member.Name;
};
But it works only if I have 1 rule that has no name and it looks not pretty.
Maybe there it is another way of achieving the same result?
The problem is that extension method you are using return an instance of IRuleBuilder<T, out TProperty> interface which doesn't contain definitions for method like WithMessage. This and other methods you mentioned are extension methods for IRuleBuilderOptions<T, TProperty> interface which inherits IRuleBuilder<T, out TProperty>.
So one of possible solutions is to wrap EntityDoesNotExist extension method into another method which will downcast the returned type to IRuleBuilderOptions<T, TProperty>
For example we have class called Person:
public class Person
{
public string Name { get; set; } = null!;
}
Extension method for Name property which returns IRuleBuilder type:
public static IRuleBuilder<T, string> ValidateNameLength<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.Must(name => name.Length < 5).WithMessage("Incorrect length");
}
So we can wrap this method something like this:
public static IRuleBuilderOptions<T, string> ValidateNameLengthWrapper<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return (IRuleBuilderOptions<T, string>) ruleBuilder.ValidateNameLength();
}
Then we can use WithMessage method to override error description:
public class Validator : AbstractValidator<Person>
{
public Validator()
{
CascadeMode = CascadeMode.Continue;
RuleFor(x => x.Name!).ValidateNameLengthWrapper().WithMessage("Name must be less than 5 characters");
}
}
But maybe would be better to write your own extension method or resolve the problem outside the validation context.

GWT with Serialization

This is my client side code to get the string "get-image-data" through RPC calls and getting byte[] from the server.
CommandMessage msg = new CommandMessage(itemId, "get-image-data");
cmain.ivClient.execute(msg, new AsyncCallback<ResponseMessage>() {
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(ResponseMessage result) {
if (result.result) {
result.data is byte[].
}
}
});
From the server side I got the length of the data is 241336.
But I could not get the value in onSuccess method. It is always goes to onFailure method.
And I got log on Apache:
com.google.gwt.user.client.rpc.SerializationException: Type '[B' was
not included in the set of types which can be serialized by this
SerializationPolicy or its Class object could not be loaded.
How can I do serialisation in GWT?
1) Create a pojo which implements Serializable interface
Let this pojo has all the data you want in the response of RPC service, in this case image-data
2) Pass this pojo in the response for your RPC service.
The below tutorial has enough information for creating RPC service
http://www.gwtproject.org/doc/latest/tutorial/RPC.html
The objects you transfer to and from the server has to implement IsSerializable.
All your custom Objects within the Object you are transferring also needs to implement IsSerializable.
Your objects cannot have final fields and needs an no argument constructor.
You need getters and setters.
A common serialize object in GWT:
public class MyClass implements IsSerializable {
private String txt;
private MyOtherClass myOtherClass; // Also implements IsSerializable
public MyClass() {
}
public String getTxt() {
return this.txt;
}
public void setTxt(String txt) {
return this.txt = txt;
}
public String getMyOtherClass() {
return this.myOtherClass;
}
public void setMyOtherClass(MyOtherClass myOtherClass) {
return this.myOtherClass = myOtherClass;
}
}

base class property always null when creating objects from xaml

I'm trying to instance an object(s) from xaml. The object's class inherits from a base class. Everything works good except that the a base class property ("Key") is not setting correctly from xaml. It's always null. The object's properties itself are set OK from xaml. Also when I set the Key property from code it sets fine.
I put a breakpoint on the closing bracket of the MainWindow method to view the object data. The hover details tells me the Key property is always null.
Any ideas what I'm doing wrong?
<?xml version="1.0" encoding="utf-8" ?>
<GroupUiItem xmlns="clr-namespace:Configurator.UiCore"
Key="key_grp1" UserName="grp1">
<ParameterUiItem Key="key_par1" UserName="par1"/>
<GroupUiItem Key="key_grp2" UserName="grp2">
<ParameterUiItem Key="key_par2" UserName="par2"/>
<ParameterUiItem Key="key_par3" UserName="par3"/>
</GroupUiItem>
<ParameterUiItem Key="key_par4" UserName="par4"/>
<ParameterUiItem Key="key_par5" UserName="par5"/>
<ParameterUiItem Key="key_par6" UserName="par6"/>
</GroupUiItem>
public partial class MainWindow : Window
{
public MainWindow()
{
GroupUiItem ConfigUi = new GroupUiItem();
InitializeComponent();
using (FileStream stream = new FileStream("XMLFile1.xaml", FileMode.Open, FileAccess.Read))
{
ConfigUi = XamlReader.Load(stream) as GroupUiItem;
}
ConfigUi.Key = "key_grp1"; // this works OK
CategoryList.ItemsSource = ConfigUi.Children;
}
}
// These are in the Configurator.UiCore namespace:
public class ConfiguratorUiItem
{
protected string _Key;
public string Key
{
get { return _Key; }
set { _Key = value; }
}
}
[ContentProperty("Children")]
public class GroupUiItem : ConfiguratorUiItem
{
private ObservableCollection<ConfiguratorUiItem> _Children = new ObservableCollection<ConfiguratorUiItem>();
public ObservableCollection<ConfiguratorUiItem> Children
{ get { return _Children; }
set { _Children = value; }
}
private string _UserName;
public string UserName
{ get { return _UserName; }
set { _UserName = value; }
}
}
public class ParameterUiItem : ConfiguratorUiItem
{
private string _ParameterType;
public string ParameterType
{
get { return _ParameterType; }
set { _ParameterType = value; }
}
private string _UserName;
public string UserName
{
get { return _UserName; }
set { _UserName = value; }
}
}
OK figured out my problem. Noob mistake. Needed to set build action to None and copy always. I had build action set to a page so it wasn't a loose xaml and wasn't updating to appropriate folder. I copied the xaml file to output directory manually when I first couldn't figure out the problem. This caused the program to always use the old file.
When I did this also had to add ";assembly=Configurator" to the end of the xmlns so that it now reads: "xmlns="clr-namespace:Configurator.UiCore;assembly=Configurator". Then it worked.

Autofac: how do I pass a reference to the component being resolved to one of its dependents?

With the following:
public class AClass
{
public ADependent Dependent { get; set; }
}
public class ADependent
{
public ADependent(AClass ownerValue) {}
}
with the following registrations...
builder.RegisterType<AClass>().PropertiesAutowired().InstancePerDependency();
builder.RegisterType<ADependent>().PropertiesAutowired().InstancePerDependency();
When I resolve an AClass, how do I make sure that 'ownerValue' is the instance of AClass being resolved, and not another instance? Thx
FOLLOW ON
The example above doesn't really catch the problem properly, which is how to wire up ADependent when registering when scanning... for example
public class AClass : IAClass
{
public IADependent Dependent { get; set; }
}
public class ADependent : IADependent
{
public ADependent(IAClass ownerValue) {}
}
// registrations...
builder.RegisterAssemblyTypes(assemblies)
.AssignableTo<IAClass>()
.As<IAClass>()
.InstancePerDependency()
.PropertiesAutowired();
builder.RegisterAssemblyTypes(assemblies)
.AssignableTo<IADependent>()
.As<IADependent>()
.InstancePerDependency()
.PropertiesAutowired();
The function I am looking for really is another relationship type like
public class ADependent : IADependent
{
public ADependent(OwnedBy<IAClass> ownerValue) {}
}
The OwnedBy indicates that ownerValue is the instance that caused ADependent to created. Does something like this make sense? It would certainly make wiring up UI components a breeze.
To extend Steven's approach, you can even Resolve() the second class, passing the first instance as a parameter:
builder.RegisterType<ADependent>();
builder.Register<AClass>(c =>
{
var a = new AClass();
a.Dependent = c.Resolve<ADependent>(TypedParameter.From(a));
return a;
});
You can register a lambda to do the trick:
builder.Register<AClass>(_ =>
{
var a = new AClass();
a.Dependent = new ADependent(a);
return a;
});