Is it possible to have two partial classes in different assemblies represent the same class? - asp.net

I have a class called 'Article' in a project called 'MyProject.Data', which acts as the data layer for my web application.
I have a separate project called 'MyProject.Admin', which is a web-based admin system for viewing/editing the data, and was build using ASP.NET Dynamic Data.
Basically I want to extend the Article class, using a partial class, so that I can augment one of its properties with a "UIHint" extender, which will allow me to replace the normal multi-line textbox with an FCKEdit control.
My partial class and extender would look like this:
[MetadataType(typeof(ProjectMetaData))]
public partial class Project
{
}
public class ProjectMetaData
{
[UIHint("FCKeditor")]
public object ItemDetails { get; set; }
}
Now this all works fine if the partial class is in the same project as the original partial class - i.e. the MyProject.Data project.
But UI behavior shouldn't sit in the Data layer, but rather, in the Admin layer. So I want to move this class to MyProject.Admin.
However, if I do that, the functionality is lost.
My fundamental question is: can I have 2 partial classes in separate projects, but both referring to the same "class"?
If not, is there a way to accomplish what I'm trying to do, without mixing data-layer logic with UI logic?

No, you cannot have two partial classes referring to the same class in two different assemblies (projects). Once the assembly is compiled, the meta-data is baked in, and your classes are no longer partial. Partial classes allows you to split the definition of the same class into two files.

As noted, partial classes is a compile-time phenomenon, not runtime. Classes in assemblies are by definition complete.
In MVC terms, you want to keep view code separate from model code, yet enable certain kinds of UI based on model properties. Check out Martin Fowler's excellent overview of the different flavours of MVC, MVP and whatnot: you'll find design ideas aplenty. I suppose you could also use Dependency Injection to tell the UI what kind of controls are viable for individual entities and attributes.
Your aim of separating concerns is great; but partial classes were intended to address entirely different issues (primarily with code generation and design-time modelling languages).

Extension methods and ViewModels are the standard way to extend data-layer objects in the frontend like this:
Data Layer (class library, Person.cs):
namespace MyProject.Data.BusinessObjects
{
public class Person
{
public string Name {get; set;}
public string Surname {get; set;}
public string Details {get; set;}
}
}
Display Layer (web application) PersonExtensions.cs:
using Data.BusinessObjects
namespace MyProject.Admin.Extensions
{
public static class PersonExtensions
{
public static HtmlString GetFormattedName(this Person person)
{
return new HtmlString(person.Name + " <b>" + person.Surname</b>);
}
}
}
ViewModel (for extended view-specific data):
using Data.BusinessObjects
namespace MyProject.Admin.ViewModels
{
public static class PersonViewModel
{
public Person Data {get; set;}
public Dictionary<string,string> MetaData {get; set;}
[UIHint("FCKeditor")]
public object PersonDetails { get { return Data.Details; } set {Data.Details = value;} }
}
}
Controller PersonController.cs:
public ActionMethod Person(int id)
{
var model = new PersonViewModel();
model.Data = MyDataProvider.GetPersonById(id);
model.MetaData = MyDataProvider.GetPersonMetaData(id);
return View(model);
}
View, Person.cshtml:
#using MyProject.Admin.Extensions
<h1>#Model.Data.GetFormattedName()</h1>
<img src="~/Images/People/image_#(Model.MetaData["image"]).png" >
<ul>
<li>#Model.MetaData["comments"]</li>
<li>#Model.MetaData["employer_comments"]</li>
</ul>
#Html.EditorFor(m => m.PersonDetails)

Add the base file as a linked file into your projects. It's still partial but it allows you to share it between both projects, keep them synchronized and at the same time have version/framework specific code in the partial classes.

I've had similar issues with this. I kept my partial classes in my Data project so in your case the 'MyProject.Data'. MetaDataClasses shouldn't go in your Admin project as you will create a circular references other wise.
I added a new Class Lib project for my MetaDataClasses e.g. 'MyProject.MetaData' and then referenced this from my Data project

Perhaps use a static extension class.

Just add class file as link in your new project and keep the same namespace in your partial class.

Since 2019 you can have 2 parts of a partial class in different assemblies using a trick. This trick is explained and demonstrated in this article:
https://www.notion.so/vapolia/Secret-feature-Xamarin-Forms-control-s-auto-registration-1fd6f1b0d98d4aabb2defa0eb14961fa
It uses at its core the MSBuild.Sdk.Extras extension to SDK like projects, which solves the limitation of having all partial parts of a class in the same assembly, by using one project with multiple simultaneous targets, effectively creating multiples assemblies in one compilation of the same project.

I may be mistaken here, but could you not simply define the ProjectMetaData class in your MyProject.Admin project?

Related

EF Code Only Inheritance on the client

(sorry for my bad english)
In a Silverlight 4 + RIA Services + EF4 Code Only application I have some classes on my DbContext that contain a "IsActive" field - I want to know from the client if a entity have this field and get it. My first thought was to use a interface:
public interface IHasActiveField
{
bool IsActive {get; set;}
}
public class Data: IHasActiveField
{
public bool IsActive {get; set;}
}
This work fine on the server but on the client, the RIA generated code do not have any reference to my interface, so I cannot test if (obj is IHasActiveField) - the same happens if I try to inherit from a base class with the IsActive field, on the client side, the class Data always inherit from Entity - I probably could use reflection to see if the field exists or just test for every type (if (obj is Data)) but if a more elegant way is possible, it would be way better :)
The following blog sounds like what you want.
"All you have to do is use a partial class for your model, and name the file with .shared.cs (or .shared.vb). This file will automatically be copied to the Silverlight project, so whatever is in it will be retained on the client. So with all of the interface implementation in that file, you’re done."
http://jeffhandley.com/archive/2009/03/30/ria-services-custom-interfaces.aspx

Models, ViewModels, DTOs in MVC 3 application

I have a web solution (in VS2010) with two sub-projects:
Domain which holds the Model classes (mapped to database tables via Entity Framework) and Services which (besides other stuff) are responsible for CRUD operations
WebUI which references the Domain project
For the first pages I've created I have used the Model classes from the Domain project directly as Model in my strongly typed Views because the classes were small and I wanted to display and modify all properties.
Now I have a page which should only work with a small part of all properties of the corresponding Domain Model. I retrieve those properties by using a projection of the query result in my Service class. But I need to project into a type - and here come my questions about the solutions I can think of:
I introduce ViewModels which live in the WebUI project and expose IQueryables and the EF data context from the service to the WebUI project. Then I could directly project into those ViewModels.
If I don't want to expose IQueryables and the EF data context I put the ViewModel classes in the Domain project, then I can return the ViewModels directly as result of the queries and projections from the Service classes.
In addition to the ViewModels in the WebUI project I introduce Data transfer objects which move the data from the queries in the Service classes to the ViewModels.
Solution 1 and 2 look like the same amount of work and I am inclined to prefer solution 2 to keep all the database concerns in a separate project. But somehow it sounds wrong to have View-Models in the Domain project.
Solution 3 sounds like a lot more work since I have more classes to create and to care about the Model-DTO-ViewModel mapping. I also don't understand what would be the difference between the DTOs and the ViewModels. Aren't the ViewModels exactly the collection of the selected properties of my Model class which I want to display? Wouldn't they contain the same members as the DTOs? Why would I want to differentiate between ViewModels and DTO?
Which of these three solutions is preferable and what are the benefits and downsides? Are there other options?
Thank you for feedback in advance!
Edit (because I had perhaps a too long wall of text and have been asked for code)
Example: I have a Customer Entity ...
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public City { get; set; }
// ... and many more properties
}
... and want to create a View which only shows (and perhaps allows to edit) the Name of customers in a list. In a Service class I extract the data I need for the View via a projection:
public class CustomerService
{
public List<SomeClass1> GetCustomerNameList()
{
using (var dbContext = new MyDbContext())
{
return dbContext.Customers
.Select(c => new SomeClass1
{
ID = c.ID,
Name = c.Name
})
.ToList();
}
}
}
Then there is a CustomerController with an action method. How should this look like?
Either this way (a) ...
public ActionResult Index()
{
List<SomeClass1> list = _service.GetCustomerNameList();
return View(list);
}
... or better this way (b):
public ActionResult Index()
{
List<SomeClass1> list = _service.GetCustomerNameList();
List<SomeClass2> newList = CreateNewList(list);
return View(newList);
}
With respect to option 3 above I'd say: SomeClass1 (lives in Domain project) is a DTO and SomeClass2 (lives in WebUI project) is a ViewModel.
I am wondering if it ever makes sense to distinguish the two classes. Why wouldn't I always choose option (a) for the controller action (because it's easier)? Are there reasons to introduce the ViewModel (SomeClass2) in addition to the DTO (SomeClass1)?
I would solve your problem by using an auto-mapping tool (like AutoMapper) to do the mapping for you. In cases where the mapping is easy (for example if all properties from one class should be mapped to properties with the same name on another class) AutoMapper will be able to do all the hook-up work for you, and you'll have to give a couple of lines of code to note that there should be a map between the two at all.
That way, you can have your entities in Domain, and a couple of view model classes in your WebUI, and somewhere (preferrably in WebUI or a sub namespace of the same) define maps between them. Your view models will in effect be DTOs, but you won't have to worry much about the conversion process between the domain and your DTO classes.
Note: I would strongly recommend against giving your Domain entities straight to the views of your MVC web UI. You don't want EF to "stick around" all the way to the front-end layer, in case you later want to use something other than EF.
introduce ViewModels which live in the
WebUI project and expose IQueryables
and the EF data context from the
service to the WebUI project. Then I
could directly project into those
ViewModels.
The trouble with this is you soon run into problems using EF trying to 'flatten' models. I encountered something similar when I had a CommentViewModel class that looked like this:
public class CommentViewModel
{
public string Content { get; set; }
public string DateCreated { get; set; }
}
The following EF4 query projection to the CommentViewModel wouldn't work as the couldn't translate the ToString() method into SQL:
var comments = from c in DbSet where c.PostId == postId
select new CommentViewModel()
{
Content = c.Content,
DateCreated = c.DateCreated.ToShortTimeString()
};
Using something like Automapper is a good choice, especially if you have a lot of conversions to make. However, you can also create your own converters that basically convert your domain model to your view model. In my case I created my own extension methods to convert my Comment domain model to my CommentViewModel like this:
public static class ViewModelConverters
{
public static CommentViewModel ToCommentViewModel(this Comment comment)
{
return new CommentViewModel()
{
Content = comment.Content,
DateCreated = comment.DateCreated.ToShortDateString()
};
}
public static IEnumerable<CommentViewModel> ToCommentViewModelList(this IEnumerable<Comment> comments)
{
List<CommentViewModel> commentModels = new List<CommentViewModel>(comments.Count());
foreach (var c in comments)
{
commentModels.Add(c.ToCommentViewModel());
}
return commentModels;
}
}
Basically what I do is perform a standard EF query to bring back a domain model and then use the extension methods to convert the results to a view model. For example, the following methods illustrate the usage:
public Comment GetComment(int commentId)
{
return CommentRepository.GetById(commentId);
}
public CommentViewModel GetCommentViewModel(int commentId)
{
return CommentRepository.GetById(commentId).ToCommentViewModel();
}
public IEnumerable<Comment> GetCommentsForPost(int postId)
{
return CommentRepository.GetCommentsForPost(postId);
}
public IEnumerable<CommentViewModel> GetCommentViewModelsForPost(int postId)
{
return CommentRepository.GetCommentsForPost(postId).ToCommentViewModelList();
}
Talking about Models, ViewModels and DTOs is confusing, personally I don't like to use these terms. I prefer to talk about Domain Entities, Domain Services, Operation Input/Result (aka DTOs). All of these types live in the Domain layer. Operations is the behavior of Entities and Services. Unless you are building a pure CRUD application the presentation layer only deals with Input/Result types, not Entities. You don't need additional ViewModel types, these are the ViewModels (in other words, the Model of the View). The View is there to translate the Operation Results to HTML, but the same Result could be serialized as XML or JSON. What you use as ViewModel is part of the domain, not the presentation layer.

ASP.NET MVC 2 Using an interface to strongly type a partial

I'm experimenting with ASP.NET MVC2, in particular viewmodels and partials. My question is: Is it ‘valid’ or ‘right’ to have your partials strongly typed against an interface and the have your viewmodels implement that interface if the view uses the partial?
To illustrate, say I have a Product form partial (strongly typed against IProductFormViewModel) which is used in both the Edit and Create views. These views are strongly typed against ProductEditViewModel and ProductCreateViewModel which implement the IProductFormViewModel.
The benefit being that the corresponding POST actions for Create and Edit take ProductCreateViewModel & ProductEditViewModel objects respectively.
Edit:
If the partial has its own dedicated viewmodel (ProductFormViewModel) and each of the ProductEditViewModel & ProductCreateViewModel expose a property of type ProductFormViewModel which is passed to the partial, then when the form is submitted the model binding of ProductEditViewModel & ProductCreateViewModel doesn't work as the Edit and Create actions expect their respective object types...thats the reason for the approach.
You may have problems when your interfaces for your different partials expose the same property name e.g. name. You would then have to explicity implement the interface which would then cause problems with your model binding.
Otherwise it should work.
Yes, this seems a valid approach.
Interfaces are essentially contracts that need to be fulfilled by implementing classes. but in case of view engines i don't see any specific benefit of having you viewmodels implement an interface because at the end you have to instantiate the viewmodel in controller and pass it to the view and suppose you change implementation of ProductFormViewModel or EditProductViewModel, u still have to instantiate (populate) the object in controller and pass it to the view. so it does not achieve the same purpose as we do in repository pattern in conjunction with dependency injection. if you can tell what exactly u are trying to achieve by this approach, we might help.
Your approach is fine.
Or you could have a model specific to your partial and use composition instead, e.g.:
public class AddressModel
{
public string Address { get; set; }
public string Code { get; set; }
}
public class PersonModel
{
public string Name { get; set; }
public AddressModel Address { get; set; }
}
Then when redering your partial you pass it the correct model.
HTH

ASP.NET MVC Design Question - Where to put DB access code?

I've been playing around with ASP.NET MVC for the past few weeks. I've got a simple web application with a form which contains a number of drop down lists.
The items in the drop down lists are stored in a database, and I'm using LINQ to SQL to retrieve them.
My question is - where's the appropriate place to put this code? From what I've read so far, it seems that it's advisible to keep the Controller 'thin', but that's where I currently have this code as it needs to be executed when the page loads.
Where should I be putting DB access code etc.? I've included an excerpt from my controller below.
Thanks.
public ActionResult Index()
{
TranslationRequestModel trm = new TranslationRequestModel();
// Get the list of supported languages from the DB
var db = new TransDBDataContext();
IEnumerable<SelectListItem> languages = db.trans_SupportedLanguages
.Select(c => new SelectListItem
{
Value = Convert.ToString(c.ID),
Text = c.Name.ToString()
});
ViewData["SourceLanguages"] = languages;
ViewData["TargetLanguages"] = languages;
return View();
Your database access code should be in a repository. Example:
public interface ITranslationRepository
{
Translation GetTransaltion();
}
and the controller would use this repository:
public class TransaltionController : Controller
{
private readonly ITranslationRepository _repository;
public TransaltionController(ITranslationRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
// query the repository to fetch a model
Translation translation = _repository.GetTransaltion();
// use AutoMapper to map between the model and the view model
TranslationViewModel viewModel = Mapper.Map<Translation, TranslationViewModel>(model);
// pass the view model to the view
return View(viewModel);
}
}
So the basic idea is the following:
The controller queries a repository to fetch a model
The controller maps this model to a view model (AutoMapper is great for this job)
The controller passes the view model to the view
The view is strongly typed to the view model and uses it to edit/display
As far as the implementation of this repository is concerned feel free to use any data access technology you like (EF, NHibernate, Linq to XML, WCF calls to remote resources over the internet, ...)
There are the following advantages:
The controller logic is completely decoupled from the data access logic
Your controllers can be unit tested in isolation
Your models are not littered with properties that should belong to the UI layer (such as SelectListItem) and thus are reusable across other types of application than ASP.NET MVC.
The view model is a class which is specifically tailored to the needs of the view meaning that it will contain specific formatted properties and the view code will be extremely readable.
Your views are strongly typed => no more ViewData and ugly magic strings
Suggest that your data-access code should be contained in its own project/assembly. That is referenced by the UI tier (ASP.NET MVC application). That'll help achieve the goal of keeping your Controllers thin, and keep all the data access code out of your MVC UI project.
That typically leads to another question/discussion about domain entities: when mapping to the data store. Some architects like to have the entities in their own separate assembly. This encourages reuse in other applications. Some like to keep the entity model and data access code in the same project/assembly. This is totally up to you and your environment.
For an example, let's say it's a billing application; holding customers, invoices, etc.
Your implementation will be different, depending on your data access strategy (an ORM like LINQ To SQL, EF, nHibernate, SubSonic, or plain old ADO.NET, or reading from a flat file).
// Assembly: InvoicingDL
public class CustomerRepo
{
public IQueryable<Customer> ListCustomers()
{
return MyDatabase.Customers(); //however you'd get all your customers
}
//etc
}
// Assembly: InvoicingDL
public class InvoicingRepo
{
public IQueryable<Invoice> GetCustomerInvoices(int custID)
{
return MyDatabase.Invoices.Where(i=>i.CustomerID==custID);
}
//etc
}
Check out the Repository pattern
https://web.archive.org/web/20110503184234/http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx
http://www.mindscapehq.com/blog/index.php/2008/05/12/using-the-unit-of-work-per-request-pattern-in-aspnet-mvc/
The idea is you abstract your data access in something called a repository that returns domain objects. Your controller can then use this repository to get the appropriate objects from the database and assign them to the model.

21 entities with the same structure. What I'm supposed to do when it's time to make a CRUD for these entities

I Have 21 entities with the same structure.
Same Attribute too.
Every entity contains these Attributes :
AreaType
ID
IsActive
LangID
TXT
ModuleType
ID
IsActive
LangID
TXT
...
What I Need to perform a generic Crud. I already know that I need to create a generic repository. My problem is to perform a kind of generic ViewModel.
How can I create a generic View for the Create Form.
I Dont know what I need to pass in the Inherits of the view to be Generic.
... Inherits="System.Web.Mvc.ViewPage<...Dont know>"
Any Idea ?
A common approach this problem is to use ViewModels. This is where you create specific classes to be used as the models in your strongly typed views. These classes would not be the ones created by EF. The ViewModel classes can have a common base that encapulate your common fields. In your data access layer you would need to move data between your ViewModel classes and your EF classes. Things like AutoMapper (from CodePlex) work really well to reduce, if not eliminate, all of the the tedious "left-hand right-hand" coding.
Not too familiar with MVC, but (assuming it fits in with your hierarchy), I think you could create an abstract class which contains the properties you need, e.g.
public abstract class ViewableObject {
public abstract int ID {get; set;}
public abstract bool IsActive {get; set;}
// etc
}
Then implement that with your normal classes (AreaType and so on), e.g:
public class AreaType: ViewableObject{
public override int ID { get; set; }
public override bool IsActive{ get; set; }
}
and make the view use the abstract class.
... Inherits="System.Web.Mvc.ViewPage<ViewableObject>"
One idea is to simply change your underlying tables. Combine AreaType and ModuleType into a single "WhateverType" table that contains a field identifying exactly what type it is. Then when you codegen your classes you'll have exactly one class to deal with.
However, there are other concerns and you should only do this if it makes sense in your application.

Resources