What is an appropriate MVC-based OOP design for my case? - c#

Suppose the following baseline design: I have a class CarElement which holds properties and methods related to both visual representation and data model/logic representation of a car:
class carElement
{
// UI related properties and methods:
public Size DrawSize { get; set; }
public Point Location { get; set; }
public void Draw()
{
// do something...
}
// data model / logic related properties and methods:
public double weight { get; set; }
public string manufacturer { get; set; }
public double CalculatePrice()
{
// do something...
return 0;
}
}
The usage of this class is as follows: Multiple instances of carElement are drawn to some canvas. Clicking each drawn car shows the properties of that car in a property grid by using propertygrid.SelectedObject = InstanceOfcarElement.
In my opinion, this design is flawed because data model and visual representation are not separated in the class design. I would like to improve the design towards MVC and I am seeking advice on good design decisions.
My current take on this would be to separate above class carElement into something like the following two classes.
class carUIElement // organizes visual representation of a car
{
public Size DrawSize { get; set; }
public Point Location { get; set; }
private carDataElement linkedCarDataElement;
public void Draw()
{
// do something...
}
}
class carDataElement // organizes data model organization of a car
{
public double weight { get; set; }
public string manufacturer { get; set; }
private carUIElement linkedCarUIElement;
public double CalculatePrice()
{
// do something...
return 0;
}
}
With that approach, the following are unclear to me:
carUIElement should know the carDataElement it is linked to, and vice versa. Are there better design approaches to this than the simple linking in above Code?
How would I best show both the UI and data model properties on the property Grid, when the drawn UIElement is clicked?
Is the overall approach viable? What about the above open points? I am missing the experience to judge that, so I would be grateful for your comments. Thank you.

Well while we should always be careful not to over intellectualize stuff, after all we as programmers are more masons than artist and even if Notre Dame church is just a construction and not art, no always will be required exorbitant decoration and acoustic chambers, suppose the next version will be as grand as the previous :)
What do i mean? I propose pragmatism with MVC, so if and if in early infancy of the program, it can have the ui model, also sometimes called the data transfer object, be identical to the logical model, that is not in itself an anti-pattern imo.
Obviously once bulding ui, we begin to have released instances with presumed constructs and when it starts to limit development of the product, how it is presented, typically when you need more info than is relevant to ui, stored on the entity, then you can lock the interface by inventing the DTO model objects and party on with the initial model.
So I get where you're going with what's behind why you might want to separate it.
Then again often we have web frontends, especially with mvc and then mostly it will be no longer a databound view, but a MVVM thingy like like Angular, React, Vue or even Blazor if for some reason you might want that, or the tradition Razor pages, really? in new development??
I try not to put anything in the DTO classes that would be lost if only the serialized JSON version is available to your view engine. So that when modernization happens, your controller/ api doesn't have to principally change.
So seperate classes for seperate concerns an no logic in data access or transfer classes, my suggestion would be something along the lines below, but to end up with your questions:
a) Linking with a navigation property in your data model makes sense if you use it to load for instance using entity framework, it is required.
In Your UI type the frequency is key, typically we like to push all data into the points so that they need nothing else to perform, but this makes sense if the class is being serialized and deserialized and you use a tool like AutoMapper to move to and from, if You're in a windows client like WPF hey your model is already on the client and already loaded up for MVVM, you're in such a much better place that you may not honestly care for front-end types, until they need to vary.
b) the question is do you always want to show both or can you hide the cardata element until they ask for it, that would dictate the choice to either let a DTO include the data from the relation or just the foreign key and have an extra lookup method available imo.
So suggestion brief:
/// <summary>
/// Drawing is a separate concern of the application
/// </summary>
class DrawManager
{
public void DrawCar(CarBase car) { }
}
/// <summary>
/// So is calculating prices
/// </summary>
class PriceManager
{
decimal CalculateCarPrice(CarBase car) { throw new NotImplementedException(); }
}
/// <summary>
/// The 2 classes share properties, invent a base class to abide by the DRY principle
/// </summary>
class CarBase
{
public Size DrawSize { get; set; }
public Point Location { get; set; }
}
/// <summary>
/// Now they are identical
/// </summary>
class carElement : CarBase
{
carDataElement CarData { get; set; }
}
/// <summary>
/// Now they are identical
/// </summary>
class carUIElement : CarBase
{
carDataElement linkedCarDataElement;
}
/// <summary>
/// The data about a car, in RDBMS typically normalized into a seperate entity like you have,
/// does UI really need any of them? Is it always needed when other members are accessed?
/// </summary>
/// <remarks>
/// we could choose to have the data model have a navigation property and then let the ui member not have it and give it a method to ackquire it,
/// but then that shouldn't get done to early and well if it always needs it, it is not yet a seperate datatype justification for the ui aspect
/// </remarks>
class carDataElement
{
public double weight { get; set; }
public string manufacturer { get; set; }
}

Related

Swagger UI Response Example Asp.Net Core Web Api

I'm using Swagger.AspNetCore to document my api. So far i was happy to use xml comments to generate response model examples until i reach the point when i've got to document embeded object. So i have simple model:
public class SummaryResult
{
/// <summary>Total Cost.</summary>
/// <value>Total Cost.</value>
/// <example>6433.2</example>
public double TotalCost { get; set; }
/// <summary>Owner.</summary>
public Owner Owner { get; set; }
}
public class Owner
{
/// <summary>Owner Name.</summary>
/// <value>Owner Name.</value>
/// <example>Michael</example>
public string Name { get; set; }
}
And Swagger UI document it only for TotalCost, Owner property just skipped whatever i do. Does anyone have a clue why this can happen? And how to fix it.
I know how to deal with List - just put on top xml comment like <list></list> but it's not my case.
Thank you
I just tested this and it shows fine on my end:
http://swagger-net-test.azurewebsites.net/swagger/ui/index#/ActionFilter/ActionFilter_Get
Here is how that looks like on the model tab:
As you can see in the image it does show the summary and the example value.
Here is the code:
https://github.com/heldersepu/Swagger-Net-Test/blob/master/Swagger_Test/Controllers/ActionFilterController.cs#L29
Educated guess there could be something else removing those elements.

How to use interfaces in DTO with ASP.NET Web API and Unity?

I'm currently implementing dependency injection in an existing ASP.NET Web API project using the Unity container.
I already manage to inject my service classes into my API controller by configuring a dependency resolver.
But for a controller function, I have to use a Data Transfer Object (DTO).
In that object, I can't find how to use my model contracts.
Here is the Web API controller method:
[HttpPost]
[Route("api/application/save")]
public IHttpActionResult SaveApplication(ApplicationUpdateDTO applicationUpdate)
{
// Inner code calling service methods expecting IApplication and
// collections of ITag as parameters.
}
And here is the DTO definition:
public class ApplicationUpdateDTO
{
public IApplication Application { get; set; }
public IEnumerable<int> DeletedTagIds { get; set; }
public IEnumerable<ITag> AddedTags { get; set; }
public IEnumerable<int> DeletedPlatformIds { get; set; }
public IEnumerable<ITag> AddedPlatforms { get; set; }
}
As a result, the DTO itself is initialized, but not the properties that are all null.
I understand why the properties cannot be set : the interfaces cannot be instanciated and it doesn't have any clue of which classes to use for that. But my Unity container does, thanks to the registration.
Is it possible to use this "link" somehow to initialize the DTO properties?
Is there a better way do this?
Notes:
If I use implementations of my interfaces in the DTO, it obviously works fine.
The controller method receives a JSON object that is identical to my DTO.
edit
I also tried the implementation of a ModelBinder by referring to this post.
But for the line about the ValueProviderResult, I got a null value.
For convenience, here is the response from Todd in the other question:
public class CreateSomethingModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
string key = bindingContext.ModelName;
ValueProviderResult val = bindingContext.ValueProvider.GetValue(key);
if (val != null)
{
string s = val.AttemptedValue as string;
if (s != null)
{
return new CreateSomething(){Title = s; UserId = new Guid(ControllerContext.HttpContext.Request.Headers["userId"]);}
}
}
return null;
}
}
The small difference I got from the response of the question, is the usage of the System.Web.Http.ModelBinding.IModelBinder instead of the MVC one.
As requested, here are exerpts of my interfaces.
The IApplication interface:
public interface IApplication
{
/// <summary>
/// Identifier of the application.
/// </summary>
int Id { get; set; }
/// <summary>
/// Name of the application.
/// </summary>
string Name { get; set; }
/// <summary>
/// Version of the application.
/// </summary>
string Version { get; set; }
/// <summary>
/// Tags associated to the application.
/// </summary>
ICollection<ITag> Tags { get; }
}
The ITag interface:
public interface ITag
{
/// <summary>
/// Identifier of the tag.
/// </summary>
int Id { get; set; }
/// <summary>
/// Identifier of the application to which the tag is linked.
/// </summary>
int ApplicationId { get; set; }
/// <summary>
/// Value of the tag.
/// </summary>
string Value { get; set; }
}
An example of JSON:
{
"marketApplication": {
"Id": 20,
"Name": "MyApplication",
"Version": "2.0"
},
"deletedTagIds": [],
"addedTags": [
{
"Id": 0,
"Value": "NewTag"
}
],
"deletedProgramIds": [],
"addedPrograms": [
{
"Id": 0,
"Name": "x86"
}
]
}
Dependency Injection is the practice of composing graphs of loosly coupled components. Components are the classes in your system that contain behaviour.
Dependency Injection is not meant to build up objects that merely contain data. Using Dependency Injection we build an graph of components. After that graph has been build (using constructor injection), we pass runtime data through this graph using method calls.
Every time you try to use Dependency Injection or an DI container (like Unity) for anything else, you will get into trouble. So although your question indicates that you want to do this with Unity, Unity should be left out of the equation (for this particular case).
As others already stated, the building of Data Transfer Objects (DTOs) that come in through the request is the job of Web API's Model Binder. The default Model Binders can't deserialize interfaces for you, which is quite obvious; to what implementation should they deserialize?
Although you can replace the default model binder, you should take a step back and look closely at what it is you are trying to achieve. You are abstracting away data. Hiding a DTO behind an abstraction makes usually little sense, since interfaces are meant to abstract behavior.
So instead of using interfaces, it is usually much better to use concrete classes instead.
it would save me the copy from a "sub-DTO" to a concrete one manually
Instead of doing that, a simpler approach would be to use composition. You can compose DTOs out of smaller DTOs. That would save you from having to do the copying completely.
by using the matching type registered in my Unity container.
This assumes that those DTOs should be registered in the container, but again, an DI container should not hold any runtime data. This should be kept out. Or as stated here:
Don't inject runtime data into application components during construction; it causes ambiguity, complicates the composition root with an extra responsibility and makes it extraordinarily hard to verify the correctness of your DI configuration. My advice is to let runtime data flow through the method calls of constructed object graphs.
Update
The idea of composition is simple, you build classes from smaller classes; rather than using inheritance or duplicating object structures. How this would look like in your case obviously depends on your needs, but I imagine that you wish to copy that ITag data to another class that has more properties:
public class SomeObject
{
// Members:
public string Name { get; set; }
public string Description { get; set; }
// Members to copy from ITag
public int Id { get; set; }
public int ApplicationId { get; set; }
public string Value { get; set; }
// more members
}
Instead, you can compose SomeObject from a concrete Tag DTO:
public class SomeObject
{
// Members:
public string Name { get; set; }
public string Description { get; set; }
public Tag Tag { get; set; }
// more members
}
This way you don't have to copy Tag's members; you only have to set the Tag property with a reference to the deserialized Tag DTO.

Architecture for achievements / badges

There's a lot of questions already about coding a badge system similar to SO, my question is different. Assume I have a web page system, badges / achievements, stored in the DB as a row with the achievement key (id), user id, and any other data.
My simple question is, where should I store the badge ID? I have one class per achievement with all the data and methods for testing if it has been earned. I imagine I may have dozens or hundreds at some point. I want the IDs to be used hard coded only once, and in one concise place, so I have no chance of accidentally changing them or mixing them up.
I could hard code them in the class, like
public int Key { get { return 15; } } // I'm calling it Key, not ID
but if I split my achievements among multiple files I don't want to have to run around looking for the highest Key when I add a new one and risk a mistake.
I could put them in some dictionary in another class...
public class AchievementSet
{
private Dictionary<int, Achievement> _achievements;
public AchievementSet()
{
_achievements = new Dictionary<int, Achievement>()
{
{ 1, new SomethingAchievement() }
};
}
}
But now the class itself doesn't know its own key, and it needs to (or does it?) If I passed it into the constructor now I risk mismatching the numbers.
Any recommendations?
In the context of Stack Overflow, I'd imagine each badge has properties such as:
Id, Name, Class (Bronze, Silver or Gold) and Description etc.
You mention that you currently have a class for each badge/achievement, each with appropriate checks for conditions on which it would be awarded.
The reason I'm suggesting you move away from the model you're looking at now (one class per achievement) is because you're going to continue to face huge problems down the road when you're navigating through 200 different classes looking for that one ID you can't recall.
By storing your badges in the table, your data is all in one logical place and not scattered across your application.
In answer to the question: So do you disagree with the accepted answer to: stackoverflow.com/questions/3162446/
Not necessarily, and I like this idea more than my earlier proposal for a single class that would check all the badges based on their ID.
Despite its name, I believe RexM is not defining the CommenterBadge itself in that file and should have named it CommenterBadgeJob. (You'll notice it has none of the traits I've defined in my answer and inherits from BadgeJob). The obvious question is "How does each badge job know which BadgeId it corresponds to?"
I would have an additional unique field in my Badge called BadgeJob by which you could lookup a badge.
enum BadgeClass {Bronze, Silver, Gold}
//This class would be inherited from the database.
public class Badge
{
public int Key {get;set;}
public string Name {get;set;}
public BadgeClass Class {get;set;}
public string BadgeJob {get;set;}
public string Description {get;set}
}
I would modify his code as follows:
public class CommenterBadgeJob : BadgeJob
{
public Badge commenter_badge {get;set;}
public CommenterBadgeJob() : base()
{
//Lookup badge
string badge_job_name = this.GetType().Name;
commenter_badge = db.Badges.Where(n=>n.BadgeJob == badge_job_name).Single();
}
protected override void AwardBadges()
{
//select all users who have more than x comments
//and dont have the commenter badge
//add badges
}
//run every 10 minutes
protected override TimeSpan Interval
{
get { return new TimeSpan(0,10,0); }
}
}
How about using an enum ?
public enum BadgeTypes
{
GoodAnswer = 1,
Commenter = 2,
Teacher = 3,
//...
}
Each BadgeJob could have a BadgeType property which would be used to populate the badge id when inserting an achievement during AwardBadges() (enum values can be persisted to integers).
I see no necessity for having one class per achievement. BadgeJob's contain all badge attribution logic and BadgeTypes suffice to represent the different badges.

C# save/retrieve an array of structures from settings file

I have a simple question (I think) that I'm not making much progress finding an answer to with Google. I have a structure as follows:
/// <summary>
/// A class to represent the sync settings for a single camera.
/// </summary>
public class CameraSyncSettings
{
public string ID { get; set; }
public string SyncPath { get; set; }
public bool OverwriteExisting { get; set; }
};
And then an array of these in the program, one for each camera:
List<CameraSyncSettings> MyCameraSettings = new List<CameraSyncSettings>();
Now, what I want to do is have a property in my settings such that I can read/write this array into it to persist the information between sessions.
How can I do this and what is the best/most efficient way?
You can achieve it by using Properties.Settings of type ListDictionary
Example:
Properties.Settings.Default.Example.Add("Setting1", new CameraSyncSettings());
Properties.Settings.Default.Example.Add("Setting2", new CameraSyncSettings());
Properties.Settings.Default.Example.Add("Setting3", new CameraSyncSettings());
Properties.Settings.Default.Save();
see link for more information : http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx
NB: You can set the Scope of Properties.Settings.Default.Example to Application or User
As we've cleared in the comments you want to use app.config: this project should pretty much cover all your needs.

Converting an existing instance of a class to a more concrete subclass

Situation: I have a large shrink wrapped application that my company bought. It is supposed to be extensible, yada, yada. It has a DB, DAL and BLL in the form of SQL and DLLs. It also has a MVC project (the extensible part) but 95% of the "Model" part is in the DAL/BLL libraries.
Problem: I need to extend one of the "Models" located in the BLL. It is an User object with 47 properties, 0 methods and no constructor. What I started was a simple deivation of their class like:
public class ExtendedUser : BLL.DTO.User
{
public bool IsSeller { get; set; }
public bool IsAdmin { get; set; }
}
This works fine if I just create a new ExtendedUser. However, it is populated by another call into their BLL like:
BLL.DTO.User targetUser = UserClient.GetUserByID(User.Identity.Name, id);
I tried the straight forward brute force attempt, which of course throws a Cast Exception:
ExtendedUser targetUser = (ExtendedUser)UserClient.GetUserByID(User.Identity.Name, id);
I am drawing a complete blank on this very simple OO concept. I don't want to write a Constructor that accepts the existing User object then copies each of the properties into my extended object. I know there is a right way to do this. Can someone slap me upside the head and tell me the obvious?
TIA
If you do want to use inheritance, then with 47 properties, something like Automapper might help you copy all the values across - http://automapper.codeplex.com/ - this would allow you to use:
// setup
Mapper.CreateMap<BLL.DTO.User, ExtendedUser>();
// use
ExtendedUser extended = Mapper.Map<BLL.DTO.User, ExtendedUser>(user);
Alternatively, you might be better off using aggregation instead of inheritance - e.g.
public class AggregatedUser
{
public bool IsSeller { get; set; }
public bool IsAdmin { get; set; }
public BLL.DTO.User User { get; set; }
}
What about this approach (basically Aggregation):
public sealed class ExtendedUser
{
public ExtendedUser(BLL.DTO.User legacyUser)
{
this.LegacyUser = legacyUser;
}
public BLL.DTO.User LegacyUser
{
get;
private set;
}
}
I don't want to write a Constructor that accepts the existing User object then copies each of the properties into my extended object.
This is typically the "right" way to do this, unless you have compile time access to the BLL. The problem is that a cast will never work- an ExtendedUser is a concrete type of User, but every User is not an ExtendedUser, which would be required for the cast to succeed.
You can handle this via aggregation (contain the instance of the User as a member), but not directly via inheritance.
This is often handled at compile time via Partial Classes. If the BLL is setup to create the classes (ie: User) as a partial class, you can add your own logic into a separate file, which prevents this from being an issue. This is common practice with many larger frameworks, ORMs, etc.

Categories

Resources