I have a Windows Form project that I would like to migrate toward a web application using ASP.NET MVC2.
In this project I have some POCO classes as in this example that are part of a class library and that I would like to use with a binary reference
public class Person
{
public int PersonID { get; set; }
public string Name { get; set; }
public DateTime BornDate { get; set; }
...
}
Is there a way to use these classes inside my Web MVC project and adding, for example validation attributes without modifying the original assembly?
thanks for helping
You may take a look at FluentValidation. It integrates nicely with ASP.NET MVC and allows you to unobtrusively add validation rules without modifying your POCO objects.
You can add Meta Information like Validation by using a Partial Class
namespace xxx.Data.yyy
{
[MetadataType(typeof(Posting_Validation))]
public partial class Posting {
}
public class Posting_Validation {
[Required(ErrorMessage = "Need title")]
[StringLength(50, ErrorMessage = "Must be under 50 characters")]
[DisplayName("Title")]
public string Title { get; set; }
[Display(AutoGenerateField = false)]
[HiddenInput(DisplayValue=false)]
public int PostingId { get; set; }
[UIHint("tiny_mce")]
public string HtmlContent { get; set; }
}
}
Related
As a learning exercise, I was trying to form a simple One to many Relation between Vendors and Shops where each Vendor has multiple shops.
Using two model classes I achieved the following:
This is what scaffolding gives me for Shops
Why am I not getting a drop down here?
Not sharing any code as of now. As most of it is auto generated. Let me know if someone would like me to paste the code for my models.
Another doubt why are my table Columns alphabetically Ordered? If I am not mistaking entity framework 6 used to order it as per the class definition. Is there a way to override it? Cause the view scaffold seems to mirror the DB in terms of ordering objects.
Thanks.
Update:
I added a property Vendorid in the Shops Class. Now I see the Dropdown but no values. Do I need to get down to Fluent API for achieving this?
public class Shops
{
public int Id { get; set; }
public String Name { get; set; }
public int Rank { get; set; }
public String Address { get; set; }
public Boolean Active { get; set; }
public int VendorId { get; set; }
public Vendors Vendor { get; set; }
}
Vendors
public class Vendors
{
public int Id { get; set; }
public String Name { get; set; }
public int Rank { get; set; }
public Boolean Active { get; set; }
public ICollection<Shops> Shops { get; set; }
}
Env: Visual Studio 2015 (Latest ASP.net Patch Applied).
Project Template: Web Application
This depends on what approach on EF you are using. Are you sure they have relationship in their classes? If your using code first, you have to map it manually using fluent API. on OnModelCreating method on DbContext class, use something like this
modelBuilder.Entity().HasMany(v => v.Shop).WithOptional(s => s.Vendor).
If your using Database First, just create relationship on tables diagram(or script) and update the model on your project and EF will create it for you.
This is my project model :
public class Project
{
public int ProjectID { get; set; }
public string ProjectTitle { get; set; }
public string ProjectDetails { get; set; }
public virtual ICollection<Proposal> Proposals{ get; set; }
}
This is my Proposal model :
public class Proposal
{
public int ProposalID { get; set; }
public string BidTitle { get; set; }
public string BidDetails { get; set; }
public virtual Project Project { get; set; }
}
As you can see, there is one-to-many relationship between Project and Proposal. In
mydomain/Project/Details/ProjectID
view, I want to put a button, when this button is clicked, user can create a new Proposal for that project. My question is how I can pass that project's information to bid? If you can give me some tips about it, I'd be really glad. Thanks.
Create a model known as a viewmodel, which includes both the models you want to use under the same view. Your would look something like this:
public class ProposalAndProjectModel
{
public Proposal Proposal { get; set; }
public Project Project{ get; set; }
}
Save it as something like ProposalAndProjectModel.cs and then in your view, reference this model.
Now in your view you will be able to do the following:
Model.Proposal.propertyName
or
Model.Project.propertyName
This should help you as for getting the correct parameters for creating new objects.
You say when user click button user goto another page. You can sen projectID as get to that page. Thats how you can get that projectID.
I have a class used by Entity Framwork, called EFApplication.
Following this link, i want to add OData query option to my Web Api controller.
However, i don't want to use EFApplication class as the query parameters.
I want to use another class used just for the OData querying (ODataApplication)
Is this possible?
One of the reasons i want to use a different class is because OData doesn't support DateTime properties, and this means that i need to change it to DateTimeOffset, which i cannot do it (without breaking many other things)
// class mapped to Entity Frameowrk / Database
public class EFApplication
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual DateTime DateCreated { get; set; }
}
// class used for OData querying only
public class ODataApplication
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class ApplicationsController : ApiController
{
[EnableQuery]
public IQueryable<EFApplication> Get(ODataQueryOptions<ODataApplication> options)
{
// how to apply ODataQueryOptions<ODataApplication> query on top of EFApplication
return result; // IEnumerable<EFApplication>
}
}
You can fix this problem with Automapper and its feature Project().To()
// ViewModel class mapped to Entity Framework Model class
public sealed class EFApplicationViewModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTimeOffset DateCreated { get; set; }
}
In your Controller for sample:
[EnableQuery]
public IQueryable<EFApplication> Get(ODataQueryOptions<ODataApplication> options)
{
IQueryable<EFApplication> queryable = EFApplicationRepository.All();
IQueryable<EFApplicationViewModel> projected = queryable.Project().To<EFApplicationViewModel>();
return projected;
}
In addition into Automapper you should set a little 'fix' for the DatetimeOffset(again sigh...)
Mapper.CreateMap<EFApplication, EFApplicationViewModel>();
Mapper.CreateMap<DateTime, DateTimeOffset>().ProjectUsing(src => src);
Mapper.CreateMap<DateTime, DateTimeOffset>().ConvertUsing(src => DateTime.SpecifyKind(src, DateTimeKind.Utc));
If you block with DateTime, now it's not a problem.
Here's latest release of Web API OData 5.4 RC.
The release note is
http://odata.github.io/WebApi/5.4-rc/
And here's a basic sample about the DateTime Support in Web API OData V4
Im developing a asp.net small website and thought about using 3-tier design pattern (Gui, BLL, DAL). My main problem is that i feel bit lost with how should i handle the caching right.
1.First, where should the caching be done? Is it in the GUI website or in the BLL?
2.Second, it feels too messy to me, any chance anyone could provide me a simple example of how caching is done in a good way with all 3 parts of the 3tier?
3.Last, do u find okay to use 3tier for my need?
Personally I really like 3-tier structure and I can only recommend it. Let's see a simple example with some minor caching. We focus on the structure now.
Let's suppose we have the following code-first structure.
public class BlogEntry
{
public int Id { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Blog> Blogs { get; set; }
}
public BlogContext : DbContext
{
public DbSet<Category> Category { get; set; }
public DbSet<BlogEntry> Entry { get; set; }
}
Mind that EF will create the primary and foreign keys in the DB by naming conventions (like "Id"). You can use Db-first model as well, not a problem.
Let's have some DTO objects (see MSDN or wiki) like:
public class CategoryDto
{
// To use in LINQ .Selector()
public Expression<Func<Category, CategoryDto>> Selector = efCategory => new CategoryDto
{
Id = efCategory.Id,
Name = efCategory.Name,
}
public int Id { get; set; }
public int Name { get; set; }
}
Of course categories are not changing often, so we may create some sort of cache for them. The caching in this case is clearly in BLL-level, using Dto objects. Update: This is good only if you have some data that is very unlikely to change but accessed very frequently. Otherwise don't bother with it.
public class MainCache
{
// Make it singleton
// Create some init and a refresh method, watch for thread-safety
public List<CategoryDto> Categories { get; set; }
}
So the controller level can access the cache like this: Update: Now the result of the action itself is cached, see details here. This is a safe solution, the framework does everything.
[HttpGet]
[OutputCache(Duration=10, VaryByParam="none")]
public ActionResult DisplayCategories()
{
// Calling BLL, receiving Dto objects
var model = MainCache.Instance.Categories;
return View(model);
}
Hope, you get it. I think this is a general structure that can be used in various situations. If something is not clear just ask.
Update: Minor code fix, and about caching
I'm following along with "Professional ASP.NET MVC 4" and trying to generate a controller from a model using Entity Framework. My Model looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace MvcMusicStore.Models
{
public class MusicStoreModels
{
public class Album
{
public virtual int AlbumId { get; set; }
public virtual int GenreId { get; set; }
public virtual int ArtistId { get; set; }
public virtual string Title { get; set; }
public virtual decimal Price { get; set; }
public virtual string AlbumArtUrl { get; set; }
public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
}
public class Artist
{
public virtual int ArtistId { get; set; }
public virtual string Name { get; set; }
}
public class Genre
{
public virtual int GenreId { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual List<Album> Albums { get; set; }
}
}
}
When I right click my Controllers folder and choose Add > Controller I select "MVC controller with read/write action and views, using Entity Framework" as my template and "Album (MvcMusicStore.Models)" as my Model class. The book tells me to select "new data context..." and name it "MvcMusicStore.Models.MusicStoreDBContext".
Everything looks OK and I have saved and built my solution prior to performing the above actions. However, I get an error message saying
There was an error generating 'MvcMusicStore.Models.MusicStoreDBContext'.
Try rebuilding your project.'
I'm at a bit of a loss. Can anyone help?
The symptoms sound a lot like this issue:
http://www.rhysgodfrey.co.uk/archive/2011/04/20/mvc3-tools-update-and-entity-framework-4-1-error.aspx
I would suggest uninstalling all versions of Entity Framework, re-installing the latest version through NuGet, and regenerating your EF context from scratch.
I not very up on C# (i think it is C# code - but dont quote me on that).....
Well after pasting your code in a new project i notice the line that says
Using System.Data.Entity;
Is flagged as an error,
And some further research shows that a refrence is POSSIBLY missing in inyour config.sys file...
Re: http://forums.asp.net/t/1381740.aspx/1