Asp.net Telerik MVC 4 Application with Unit Test Project - asp.net-mvc

I created a Asp.net Telerik MVC 4 Application that has a unit project in it. When I tried to initialize a user object in the unit test, it failed. It gave an error message that said the connection string does not exist in the config file. However, I check the config file, and the connection string is there.
here are some sample codes:
//Connection String
<connectionStrings>
<add name="KMSSEntities" connectionString="metadata=res://*/Models.KMSSEntityModel.csdl|res://*/Models.KMSSEntityModel.ssdl|res://*/Models.KMSSEntityModel.msl;provider=System.Data.SqlClient;provider connection string="data source=(local);initial catalog=KMSS;persist security info=True;user id=******;password=*******;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
//Initialize my Context
private KMSSEntities entity = new KMSSEntities();
//This is my insert user
public void InsertUser(User user)
{
entity.Users.Add(user);
}
//this is code in the test method
User u = new User();
u.UserName = "test";
u.password = "Password";
u.FirstName = "first";
u.LastName = "Last";
StudentRepository rep = new StudentRepository(new KMSSEntities());
rep.InsertUser(u); **//This is where it's returning the error message**
rep.Save();
//This is the stack trace.
at System.Data.Entity.Internal.LazyInternalConnection.get_ConnectionHasModel()
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
at System.Data.Entity.DbSet`1.Add(TEntity entity)
at KMSS.Models.UserRepository.InsertUser(User user) in c:\com\KMSS\KMSS\KMSS\Models\UserRepository.cs:line 29
at KMSSTests.UnitTest1.TestMethod1() in c:\com\KMSS\KMSS\KMSSTests\UnitTest1.cs:line 21

Related

Wildfly 8 custom login module accessing HttpServletRequest params

I am investigating the feasibility of using a wildfly custom login module.
The client will pass the mobile device id to the server as part of the login. I will check that the username and password are correct in the usual way then I need to check that the mobile device is approved to use the service.
The idea is that I will have a restful webservice method login that calls HttpServletRequest.login(u, p).
How do I get hold of the mobile device id inside the login module in the HttpServletRequest?
I could login and if that succeeds then test the device id in the webservice and if that is not approved, log the user out. But that seems rather messy.
What is the correct way of doing this?
EDIT
FEED BACK: I did it the way chris suggested. I implemented my own version of the CallBackHandler and an implementation of the Callback interface, inside the login method of my login module I do the following:
public boolean login() throws LoginException {
boolean login = super.login();
if (login) {
UuidCallback uuidCallback = new UuidCallback();
try {
super.callbackHandler.handle(new Callback[]{uuidCallback});
} catch (Exception e) {
LoginException le = new LoginException("Failed to get uuid");
le.initCause(e);
throw le;
}
System.out.print("Device UUID: "+uuidCallback.getUuid());
}
return login;
}
Inside the web service login method :
#Path("/login")
#Produces({ "application/json" })
public class LoginWebService {
#POST
public Response login(#Context HttpServletRequest request) throws LoginException {
CallbackHandler callbackHandler = new MyCallbackHandler(request.getParameter("username"), request.getParameter("password"), request.getParameter("uuid"));
Subject subject = new Subject();
LoginContext loginContext = new LoginContext("securityDomain", new subject, callbackHandler);
loginContext.login();
MyPrincipal principal = subject.getPrincipals(MyPrincipal.class).iterator().next();
}
}
You could also just set the uuid on the callback handler and then call getUUID() on the callback handler inside the LoginModule.login method. But I opted to go with the design even though it does not quite make sense to me.
I was still getting 403 when logged in and trying to access protected resources it turns out that if auth-constraint/role-name is *, you must supply at least one security-role.
<login-config>
<auth-method>FORM</auth-method>
<realm-name>mydomain</realm-name>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>rest</web-resource-name>
<url-pattern>/rest/app/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<!-- after login there is a 403 on protected resources if no role and role-name * -->
<security-role>
<role-name>user</role-name>
</security-role>
All my users have a role user, which gives them access. I was able to get it working by excluding the security-role but then auth-constraint/role-name must be set to a literal role, in my case: "user"
I would suggesting creating a LoginContext and pass thru an implementation of a CallbackHandler. In the callbackhandler cater for the extra UUID property.
While this code works for me, you will need to update it to cater for the extra UUID property
public class NamePasswordCallbackHandler implements CallbackHandler {
private final String username;
private final String password;
private NamePasswordCallbackHandler(String username, String password) {
this.username = username;
this.password = password;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (Callback current : callbacks) {
if (current instanceof NameCallback) {
((NameCallback) current).setName(username);
} else if (current instanceof PasswordCallback) {
((PasswordCallback) current).setPassword(password.toCharArray());
} else {
throw new UnsupportedCallbackException(current);
}
}
}
}
I created my own implementation of the Configuration object (shown below as JBossJaasConfiguration).
Then pass thru this callbackhandler to your LoginContext:
CallbackHandler cbh = new NamePasswordCallbackHandler(username, password);
Configuration config = new JBossJaasConfiguration("mysqldomain");
LoginContext loginContext = new LoginContext("mycontext", new Subject(), cbh, config);
loginContext.login();
The property "mysqldomain" relates to the security-domain name in your standalone.xml
<subsystem xmlns="urn:jboss:domain:security:1.2">
<security-domains>
<security-domain name="mysqldomain" cache-type="default">
<authentication>
<login-module code="com.soccerx.security.DatabaseServerLoginRealm" flag="required">
<module-option name="dsJndiName" value="java:jboss/datasources/SoccerSoftwareDS"/>
<module-option name="principalsQuery" value="select userId, tenantId, password, salt from User where username=? and StatusId != 2"/>
<module-option name="rolesQuery" value="select Role, 'Roles' from User where Username=?"/>
<module-option name="password-stacking" value="useFirstPass"/>
<module-option name="principalClass" value="com.soccerx.security.DatabasePrincipal"/>
</login-module>
</authentication>
</security-domain>
<security-domains>
</subsystem>
While this is not a complete solution for your needs, I expect you can modify it to ensure that login fails should the UUID not match.
Note: You will need to cater for this in your CustomDatabaseLoginRealm, as defined in your standalone.xml. Meaning access the username/password/uuid and compare it to the values in the database.
More more documentation see here
Instead of calling HttpServletRequest.login() method directly from your restful webservice, you could configure a security-domain in Wildfly.
This security-domain should be referenced in your webapp web.xml file login-config element, with a security-constraint, to enable JAAS
Here is an example of web.xml file which declares a security-constraint and a login-config (with BASIC authentication method)
And a Wildfly standalone.xml configuration sample for security-domain configuration, using a standard provided Database login-module, not a custom one:
<security-domain name="securityDomain" cache-type="default">
<authentication>
<login-module code="Database" flag="required">
<module-option name="dsJndiName" value="java:/TestDS"/>
<module-option name="principalsQuery" value="select password from User where login = ? and (disabled is null or disabled = 0) and activated = 1"/>
<module-option name="rolesQuery" value="select name,'Roles' from Role r, User_Role ur, User u where u.login=? and u.id = ur.userId and r.id = ur.roleId"/>
<module-option name="hashAlgorithm" value="SHA-256"/>
<module-option name="hashEncoding" value="base64"/>
<module-option name="unauthenticatedIdentity" value="guest"/>
</login-module>
</authentication>
</security-domain>
Then, in your REST resource, you just have to use the #RolesAllowed or #PermitAll annotations to restrict access or not doing also authorization.

How to set Password and Username in web.config

In my MVC Application I use the connection string is set in the Web.config via
Private connectionString As String = ConfigurationManager.ConnectionStrings("DBCS").ConnectionString
and have no problems with my db connection. But since I need a password and username to log into my database I hardcoded that in the web.config
<connectionStrings>
<add name="DBCS" connectionString="server=win\SQLExpress;database=myDb; uid=myUsername;password=myPassword" providerName="System.Data.SqlClient" />
</connectionStrings>
I am looking for a way to send the password and username from the userinterface to the config.web file first off I thought the ConfigurationManager Class should provide a property for that but I cannot find something. Can anyone explain to me how to do this?
You can save this value in app settings:
<appSettings>
<add key="DBCS" value="Data Source=win\SQLExpress;Initial Catalog=myDb;User ID={0};Password={1}" />
</appSettings>
and then do the following:
using System.Data.SqlClient;
public void DoDatabaseOperations(string _Username, string _Password)
{
string connetionString = null;
SqlConnection cnn ;
connetionString = string.Format(ConfigurationManager.AppSettings("DBCS"), _Username, _Password);
cnn = new SqlConnection(connetionString);
try
{
cnn.Open();
// your code here
cnn.Close();
}
catch (Exception ex)
{
// handle exception
}
}
VB.NET Equivalent:
Imports System.Data.SqlClient
Public Sub DoDatabaseOperations(_Username As String, _Password As String)
Dim connetionString As String = Nothing
Dim cnn As SqlConnection
connetionString = String.Format(ConfigurationManager.AppSettings("DBCS"), _Username, _Password)
cnn = New SqlConnection(connetionString)
Try
cnn.Open()
' your code here
cnn.Close()
' handle exception
Catch ex As Exception
End Try
End Sub

Entity Framework with oracle can´t change connection string

I´m using Entity Framework (latest Version) with the Oracle Driver (latest Version) in an ASP.NET MVC 5 Application. I want to set the connection string for my model during runtime, but every time I do it receives the data from the table that I used to create the model. It´s the same when I change the connection string in the web.config. Does anybody know why it behaves this way?
this is how i create the connection string:
public static string CreateConnectionString(string userName, string service)
{
const string providerName = "Oracle.ManagedDataAccess.Client";
OracleConnectionStringBuilder oraBuilder = new OracleConnectionStringBuilder();
oraBuilder.DataSource = service + ":1521/" + service;
oraBuilder.UserID = userName;
oraBuilder.Password ="xxx";
oraBuilder.PersistSecurityInfo = true;
EntityConnectionStringBuilder efBuilder = new EntityConnectionStringBuilder();
efBuilder.Metadata = "res://*/Model2.csdl|res://*/Model2.ssdl|res://*/Model2.msl";
efBuilder.Provider = providerName;
efBuilder.ProviderConnectionString = oraBuilder.ConnectionString;
return efBuilder.ConnectionString;
}
this is the overload of the model´s constructor:
public Entities(string connectionString)
: base(connectionString)
{
}
this ist my connection string:
try this connection string:
<connectionStrings>
<add name="VoccDbContext" connectionString="metadata=res://*/Entities.Vocc.VoccModel.csdl|res://*/Entities.Vocc.VoccModel.ssdl|
res://*/Entities.Vocc.VoccModel.msl;provider=Oracle.DataAccess.Client;provider connection string="DATA SOURCE=sameDbName;PASSWORD=somePass;USER ID=someUser;""providerName="System.Data.EntityClient" />
</connectionStrings>
DIRECTORY_SERVERS=(tnsnames.somesite.org:389:636)
DEFAULT_ADMIN_CONTEXT="dc=site,dc=com"
DIRECTORY_SERVER_TYPE=OID
here( LDAP.ORA file) to be modified with correct LDAP Parameters
Do not edit XXXModels.cs. Try to edit XXXModels.Context.tt.
Add following code after public <#=code.Escape(container)#>()...}
public <#=code.Escape(container)#>(string connectionString)
: base(connectionString)
{
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
}
foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
{
// Note: the DbSet members are defined below such that the getter and
// setter always have the same accessibility as the DbSet definition
if (Accessibility.ForReadOnlyProperty(entitySet) != "public")
{
#>
<#=codeStringGenerator.DbSetInitializer(entitySet)#>
<#
}
}
#>
}

OData get object by field other than Id

I have just started working with Web Api OData and I find myself wanting to do something that I was able to do a standard ApiController, that is get an object from a field other than the Id field. I know it is standard to do this for example when getting an object based on it's Id :
[Queryable]
public SingleResult<Group> GetGroup([FromODataUri] int key)
{
return SingleResult.Create(db.Groups.Where(group => group.GroupId == key));
}
But if I want to get group by groupName field for example, what would I do? I have tried this as something similar worked with an ApiController :
Controller :
public Group GetGroup([FromODataUri] string groupName)
{
var group = _repository.GetGroupByGroupName(groupName);
if (group == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return group;
}
Repository :
public Group GetGroupByGroupName(string groupName)
{
Group group = (from u in _db.Groups
where u.GroupName == groupName
select u).FirstOrDefault();
return group;
}
My WebApiConfig looks like this :
public static void Register(HttpConfiguration config)
{
config.EnableCors();
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
// OData
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<City>("Cities");
modelBuilder.EntitySet<Stage>("Stages");
modelBuilder.EntitySet<Team>("Teams");
modelBuilder.EntitySet<Fixture>("Fixtures");
modelBuilder.EntitySet<Roster>("Rosters");
modelBuilder.EntitySet<Standing>("Standings");
modelBuilder.EntitySet<Group>("Groups");
var model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute("ODataRoute", "odata", model);
}
I want to be able to get a group object based on a groupname using odata/Groups/GroupName, but what I currently have does not work. How would I do this, or am I approaching this from totally the wrong direction?
You are already using QueryableAttribute so if you define something like:
[Queryable]
public IQueryable<Group> Get()
{
// Returns all groups as a queryable (do not execute query here!)
}
You can then access this with an ajax request and any odata query, like:
http://server/Api/Group?$filter=GroupName eq 'test'
The query is built on the client, not restricted by server parameters.
Let's say you STILL need to call a custom function. OData V4 allows that. The question is a bit old but I believe it is still valid today.
First, you need to specify a Namespace to the ODataConventionModelBuilder since OData V4 needs this for actions and functions:
var builder = new ODataConventionModelBuilder();
builder.Namespace = "Default";
Be aware that this might result in IIS giving 404 because the dot is interpreted by IIS. To prevent this, add the following to your Web.config:
<system.webServer>
<handlers>
<clear/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="/*"
verb="*" type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
then, you need to declare the function too:
builder.EntitySet<Group>("Groups").EntityType
.Collection
.Function("GetGroupByName")
.ReturnsFromEntitySet<Group>("Groups")
.Parameter<string>("name");
Notice the function is declared on the COLLECTION, so it's bound to it. Then the ODataController method:
[ODataRoute("Groups/Default.GetGroupByName(name={name})")]
[HttpGet]
public IHttpActionResult GetGroupByName([FromODataUri]string name)
{
return Ok(new Group() or whatever);
}
Here the ODataRoute annotation is necessary only if you use a parameter. It defines in order: the entityset, the namespace, the method and the parameters.
You can then use:
http://localhost:xxxx/api/Groups/Default.GetByGroupName(name='sausage')
Also, see this SO answer to pass multiple parameters

How create multiple db context instances by connecting strings?

In C#, MVC code first application I have
public class CarContext : DbContext { }
class in first version of application. And connection string is like
<add name="CarContext" providerName="System.Data.SqlClient" Integrated Security=true;
connectionString="Data Source=Dragon; Initial Catalog=CarDBv1;"/>
When I run application, first version of database is created - CarDBv1.
Then I edit my CarContext class, for example, add new table, change any property etc., also change version of application, change connection string
Initial Catalog=CarDBv1; to Initial Catalog=CarDBv2; and run project. In this case I have 2 database: CarDBv1 and CarDBv2. But, CarContext class is same in applications.
Now, I need to connect both database and their context(CarContext) from any console application and use their tables for converting, reading etc.
I found a similar answer here: https://stackoverflow.com/a/16860878/1534785
But in my applications context name is same.
How can I create 2 instances for every CarContext in applications by their database connection string?
You can use an overloaded constructor to DbContext to allow contexts to point at and arbitrary database which is NOT declared in app.config.
See the constructor with dbConnection.
public class MyDbContext : DbContext, IContextOptions {
//ctors
protected BosBaseDbContext(string connectionName)
: base(connectionName) { }
protected BosBaseDbContext(DbConnection dbConnection, bool contextOwnsConnection)
: base(dbConnection, contextOwnsConnection) { }
}
usage
//datasource could be localhost, DBName the catalog name
new MyDbContext((GetSqlConn4DbName(dataSource,dbName )),true);
public DbConnection GetSqlConn4DbName(string dataSource, string dbName) {
var sqlConnStringBuilder = new SqlConnectionStringBuilder();
sqlConnStringBuilder.DataSource = String.IsNullOrEmpty(dataSource) ? DefaultDataSource : dataSource;
sqlConnStringBuilder.IntegratedSecurity = true;
sqlConnStringBuilder.MultipleActiveResultSets = true;
var sqlConnFact = new SqlConnectionFactory(sqlConnStringBuilder.ConnectionString);
var sqlConn = sqlConnFact.CreateConnection(dbName);
return sqlConn;
}

Resources