I am trying to connect oracle with MVC as below
Config file
<connectionStrings>
<add name="OracleDbContext" providerName="Oracle.ManagedDataAccess.Client" connectionString="User Id=test;Password=123_test;Data Source=local:xxxx/liveprod" />
</connectionStrings>
User table model
public class sys_users
{
[Key]
public long us_id { get; set; }
public string us_name { get; set; }
public string us_pass { get; set; }
}
Db context
public class OracleDBContext : DbContext
{
public OracleDBContext()
: base("name=OracleDbContext")
{
}
public virtual DbSet<sys_users> sys_users { get; set; }
}
Controller
public ActionResult Login(string Name, string Password)
{
var u = db.sys_users.Where(d => d.us_name.Equals(Name) && d.us_pass.Trim().Equals(Password)).FirstOrDefault();
if (u != null)
{
Session["LoggedInAdminUserId"] = u.us_id.ToString();
Session["LoggedInAdminUsername"] = u.us_name.ToString();
return RedirectToAction("Login");
}
else
{
ViewBag.message = "Username or Password is invalid.";
}
return View();
}
But at the line
var u = db.sys_users.Where(d => d.us_name.Equals(Name) && d.us_pass.Trim().Equals(Password)).FirstOrDefault();
I am getting error
ORA-01918: user 'dbo' does not exist
Do I need to do anything else for using oracle tables as model in MVC??
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Configure default schema
modelBuilder.HasDefaultSchema("STORE");
}
Entity default schema user is based on Sql (dbo) change the default to anything else but in UPPERCASE
Related
I am working on an intranet site with Windows Authentication for logins. However, I want to extend the IPrincipal to have other properties. For instance, I'd like to get the user's FirstName in #User.FirstName or User.AuthorizedActivity("Admin/Permissions/Edit") (would retrieve from db) using activities instead of roles to hide certain links, etc. I am really having a heck of a time figuring this out over the past 2 days and find much information doing this with Windows Authentication.
My CustomPrincipal and BaseViewPage setup:
namespace Intranet_v2.Helpers
{
public interface ICustomPrincipal : IPrincipal
{
Guid UserGuid { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get; set; }
}
public class CustomPrincipal : ICustomPrincipal
{
public IIdentity Identity { get; private set; }
public bool IsInRole(string role) { return false; }
public CustomPrincipal(string identity)
{
this.Identity = new GenericIdentity(identity);
}
public Guid UserGuid { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
}
public class CustomPrincipalSerializeModel
{
public Guid UserGuid { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
}
public class BaseController : Controller
{
protected virtual new CustomPrincipal User
{
get { return HttpContext.User as CustomPrincipal; }
}
}
public abstract class BaseViewPage : WebViewPage
{
public virtual new CustomPrincipal User
{
get { return base.User as CustomPrincipal; }
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual new CustomPrincipal User
{
get { return base.User as CustomPrincipal; }
}
}
}
Views Web.Config BaseViewPage:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="Intranet_v2.Helpers.BaseViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization"/>
<add namespace="System.Web.Routing" />
<add namespace="Intranet_v2" />
</namespaces>
</pages>
I think my main problem is I have no idea what to do in the protected void Application_PostAuthenticateRequest(object sender, EventArgs args) for my Global.asax.cs file. I have a poor attempt at setting it up here:
protected void Application_PostAuthenticateRequest(object sender, EventArgs args)
{
//var application = (HttpApplication)sender;
var context = application.Context;
if (context.User != null || !context.User.Identity.IsAuthenticated) return;
var formsIdentity = (FormsIdentity)context.User.Identity;
if (formsIdentity == null) return;
var ticket = formsIdentity.Ticket;
JavaScriptSerializer serializer = new JavaScriptSerializer();
CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(ticket.UserData);
CustomPrincipal newUser = new CustomPrincipal(ticket.Name);
newUser.UserGuid = serializeModel.UserGuid;
newUser.FirstName = serializeModel.FirstName;
newUser.LastName = serializeModel.LastName;
newUser.FullName = serializeModel.FullName;
var values = ticket.UserData.Split('|');
var roles = values[1].Split(',');
context.User = new GenericPrincipal(new GenericIdentity(ticket.Name, "Forms"), roles);
}
Now I'm at the point where #User.Name is now null. I'm in way over my head on this. Any help is appreciated. My protected void Application_PostAuthenticateRequest(object sender, EventArgs args) is completely out of wack.
All I want to do is rely on Windows Authentication to do what it does normally and add a few extra properties to the HttpContext.Current.User. Any help is appreciated... I can't be the only one trying to do this.
What I normally do is just request the additional user information later. For instance, using an Extension method like:
public static class PrincipalExtensions
{
private static void Initialize(string userName)
{
var userRecord = //Get user information from DB;
var session = HttpContext.Current.Session;
if (session != null)
{
session.Add("UserID", userRecord.ID);
session.Add("UserEmail", userRecord.Email);
//And so on
}
}
public static long? GetUserID(this IPrincipal user)
{
var id = HttpContext.Current.Session["UserID"] as long?;
if (id == null)
Initialize();
return (long)HttpContext.Current.Session["UserID"];
}
}
This is roughly what I implement in some of my projects; rather than tapping into the login process and store it in the cookie, the system can lazy load the information and cache in session when the information is needed.
I am in the process of Downgrading from EF7 to EF6 due to business decisions. I have looked at several examples but cannot seem to get it to work.
Here is what I have for EF 7
Context:
public class OwnerContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(#"Server=server\testdbs;Database=test;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Owner>(entity =>
{
entity.ToTable("Owner");
entity.Property(e => e.Id)
.HasMaxLength(50)
.HasColumnType("varchar");
});
}
public virtual DbSet<Owner> Owner { get; set; }
}
Owner Model
public class Owner
{
public int OwnerId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
How I use it
static void Main(string[] args)
{
using (var context = new OwnerContext())
{
var owner = new Owner
{
Name = "First Name",
Age = 4
};
context.Owner.Add(owner);
context.SaveChanges();
Console.ReadLine();
}
}
I got this to work with no issues and I get records in the data base. For EF 6 it is a little different
Here is what I have for EF6
Context
public class OwnerContext : DbContext
{
public OwnerContext(string connectionString) : base(connectionString) { }
public OwnerContext()
: this("OwnerConn")
{
}
public virtual DbSet<Owner> Owner{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var owner = modelBuilder.Entity<Owner>().ToTable("Owner");
owner.Property(e => e.OwnerId)
.HasMaxLength(50)
.HasColumnType("varchar");
owner.HasKey(u => u.OwnerId);
}
}
Model
public class Owner
{
public int OwnerId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
How I use it
static void Main(string[] args)
{
try
{
using (var context = new OwnerContext())
{
var person = new Owner
{
Name = "Test Name",
Age = 5
};
context.Owner.Add(person);
context.Entry(person).State = EntityState.Added;
context.SaveChanges();
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
Console.ReadLine();
}
ConnectionString
<connectionStrings>
<add name="OwnerConn" connectionString="Server=server\testdbs;Database=test;Trusted_Connection=True;" providerName="System.Data.SqlClient" />
</connectionStrings>
It seems to be very simple based on the tutorials. Hoever, I cant seem to get the changes to be reflected in the database. However, when I restart the console app and pull the records like this.
var rows = from a in context.Owner select a
It returns rows but I still don't see them in the DB. I'm out of ideas so hopefully someone can help.
I am using code first EF and new to this framework. I am trying to create a database using Database.SetInitializer but it looks like I need SQL Server Express. But I have to create database in SQL Server 2014. How to do this?
Can anybody explain this with the example from EF-dbcontext book which has following classes.
public class BreakAwayContext : DbContext
{
public DbSet<Destination> Destinations { get; set; }
public DbSet<Lodging> Lodgings { get; set; }
public DbSet<Trip> Trips { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<Reservation> Reservations { get; set; }
public DbSet<Payment> Payments { get; set; }
public DbSet<Activity> Activities { get; set; }
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new InitializeBagaDatabaseWithSeedData());
try
{
using (var context = new BreakAwayContext())
{
foreach (var destination in context.Destinations)
Console.WriteLine(destination.Name);
}
}
catch(Exception ex){
Console.WriteLine(ex.ToString());
}
Console.Read();
}
}
public class InitializeBagaDatabaseWithSeedData : DropCreateDatabaseAlways<BreakAwayContext>
{
protected override void Seed(BreakAwayContext context)
{
context.Destinations.Add(new Destination
{
Name = "Hawaii",
Country = "USA",
Description = "Sunshine, beaches and fun."
});
context.Destinations.Add(new Destination
{
Name = "Wine Glass Bay",
Country = "Australia",
Description = "Picturesque sandy beaches."
});
}
Set your connection string in your constructor:
public class BreakAwayContext : DbContext
{
public BreakAwayContext()
: base("MyConnectionString", throwIfV1Schema: false)
{
}
...
Then set your connection string in web.config or app.config:
<connectionStrings>
<add name="MyConnectionString" connectionString="Data Source=servername;Initial Catalog=dbname;..." providerName="System.Data.SqlClient" />
</connectionStrings>
I am trying to extend the UnitOfWork pattern that I used for a number of MVC 4 applications to MVC 5 whilst also using the new IdentityDbContext and things are not working out. The problem is its very hard to debug as no errors are being generated.
First, some code.
I have a context definition that looks as follows. I have added my own DbSets to the out of the box IdentityDbContext as it makes sense to keep everything in one place.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<PALSOfficer> PALSOfficers { get; set; }
public DbSet<Client> Clients { get; set; }
public DbSet<GP> GPs { get; set; }
public DbSet<Surgery> Surgeries { get; set; }
public DbSet<Disability> Disabilities { get; set; }
public DbSet<Area> Areas { get; set; }
public DbSet<PALSReferral> PALSReferrals { get; set; }
public DbSet<Appointment> Appointments { get; set; }
public ApplicationDbContext()
: base("DefaultConnection")
{
}
}
I then have a UnitOfWork class that looks as follows:
public class UnitOfWork : IDisposable
{
private bool _disposed = false;
private ApplicationDbContext _context = new ApplicationDbContext();
public UserManager<ApplicationUser> _userManager { get; set; }
private PalsOfficerRepository _palsOfficerRepository;
private UserRepository _userRepository;
private GenericRepository<Area> _areaRepository;
public UserRepository UserRepository
{
get
{
if (this._userRepository == null)
{
this._userRepository = new UserRepository(_context);
}
return _userRepository;
}
}
public PalsOfficerRepository PalsOfficerRepository
{
get
{
if (this._palsOfficerRepository == null)
{
this._palsOfficerRepository = new PalsOfficerRepository(_context);
}
return _palsOfficerRepository;
}
}
public GenericRepository<Area> AreaRepository
{
get
{
if (this._areaRepository == null)
{
this._areaRepository = new GenericRepository<Area>(_context);
}
return _areaRepository;
}
}
public UserManager<ApplicationUser> UserManager
{
get
{
if (this._userManager == null)
{
this._userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(_context));
}
return _userManager;
}
}
public void Save()
{
try
{
_context.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
throw;
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (this._userManager != null)
{ this._userManager.Dispose(); }
_userManager.Dispose();
}
this._disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
So far so good. I am using code first to generate my database with automatic migrations.
My problem is that if I try to query the database, odd things happen. Take this method for instance.
var results = new SearchResults<PALSOfficer>();
var officers = from o in Context.PALSOfficers
select o;
if (!string.IsNullOrEmpty(keyword))
{
officers = (from o in officers
where o.FirstName.Contains(keyword) || o.LastName.Contains(keyword)
select o);
}
officers = officers.OrderBy(p => p.LastName);
results.Total = officers.Count();
int offset = page * display;
results.ResultList = results.Total > offset ? officers.Skip(offset).Take(display) : officers;
//results.ResultList = Context.PALSOfficers;
return results;
This returns nothing even though the database contains data. Weirdly, the count will work. If I put a breakpoint in and mouseover the results I get the message that 'children could not be evaluated'
If I simply return Context.PALSOfficers I get the rows back. Any type of manipulation of that data though (sorting etc) seems to break the query entirely.
Here is the definition of PALSOfficer
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public DateTime Added { get; set; }
public DateTime Updated { get; set; }
}
public class PALSOfficer : ApplicationUser
{
public string InternalReference { get; set; }
public virtual ICollection<Area> Areas { get; set; }
}
I am trying to use a combination of Domain Driven Design with Test Driven Development for this application I am building in ASP.NET MVC 3. My archictecture is set up with Repositories, Domain Models, View Models, Controllers and Views. All validation will be handled in the view model. I set up my view model to inherit from "IValidatableObject" so that my validation attributes and my custom validation that i set up in the "Validate" method are both executed when my controller method calls "ModelState.IsValid". The problem I am running into is accessing my repository in the Validate method of my view model. I need to access the repository to check for duplicate records in the database. It seems like the best idea would be to create a property of IRepository type and set that property by passing injecting my repository into the constructor of the view model. For example:
public class UserViewModel : IValidatableObject
{
public UserViewModel(User user, IUserRepository userRepository)
{
FirstName = user.FirstName;
LastName = user.LastName;
UserRepository = userRepository;
UserName = user.UserName;
}
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public IUserRepository UserRepository { get; set; }
public IEnumerable<ValidationResult> Validate()
{
UserCriteria criteria = new UserCriteria { UserName = this.UserName };
IList<User> users = UserRepository.SearchUsers(criteria);
if (users != null && users.count() > 0)
{
yield return new ValidationResult("User with username " + this.UserName + " already exists."
}
}
}
Do you guys think this is a good idea?
It is good enough but if I were you, I would use
...
private readonly Func<IUserRepository> userRepositoryFactory;
...
public IEnumerable<ValidationResult> Validate()
{
UserCriteria criteria = new UserCriteria { UserName = this.UserName };
using(var UserRepository = userRepositoryFactory())
{
IList<User> users = UserRepository.SearchUsers(criteria);
if (users != null && users.count() > 0)
{
yield return new ValidationResult("User with username " + this.UserName + " already exists."
}
}
}
You can add Domain Service class to get object match with your criteria and validated at domain service level
public class PurchaseOrder
{
public string Id { get; private set; }
public string PONumber { get; private set; }
public string Description { get; private set; }
public decimal Total { get; private set; }
public DateTime SubmissionDate { get; private set; }
public ICollection<Invoice> Invoices { get; private set; }
public decimal InvoiceTotal
{
get { return this.Invoices.Select(x => x.Amount).Sum(); }
}
}
public class PurchaseOrderService
{
public PurchaseOrderService(IPurchaseOrderRepository repository)
{
this.repository = repository;
}
readonly IPurchaseOrderRepository repository;
public void CheckPurchasedOrderExsist(string purchaseOrderId)
{
var purchaseOrder = this.repository.Get(purchaseOrderId);
if (purchaseOrder != null)
throw new Exception("PO already exist!");
}
}