Limit c# model class parameter call to MS SQL server for non-existing table field - sql-server

Working with database-first approach creating ASPNETCORE MVC web app with user authentication, I would like to override the way the parameters from IdentityUser class are queried to the database. The reason is the current implementation of IdentityUser has two new parameters NormalizedEmail and NormalizedUserName (which in my opinion retracts from Normalization).
Is there a way I can write the code below in the Model class so that those two parameters are not included in the query to the database or is that something that needs to be done in the controller class?
public class IdentityUser : Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser
{
public override string NormalizedUserName
{ get { return null; } set { value = null; } }
public override string NormalizedEmail
{ get { return null; } set { value = null; } }
}

Not far as I can tell, both parameters are part of the data model and as explained in this Issue #351
About Identity 3.0:
...Instead we compute a normalized representation of the user name and we
store it in a separate column so that lookups by normalized user name
should now be sargable.
So in other words, if you "override the way the parameters from IdentityUser class are queried to the database" in essence you'll be doing exactly the opposite the class intends to do.

Related

Not Nullable fields in SQL Server Still Considered Required Fields in ASP.NET MVC

I have a non nullable fields in a table with default values set already in the property "Default Value or Binding" in SSMS. I linked this table in an ASP.Net mvc application. When I created the view and when running the create view, it still asking me to enter the required fields for the non nullable fields even though i assigned a default value for them.
After this I removed the line:
#Html.ValidationMessageFor(model => model.position, "", new { #class = "text-danger" })
which is bellow each
#Html.EditorFor statement, but this time it post me back to the same page with no changes in the database.
How can I get rid of the message in the required fields as I have already default value for them?
Simply you can create a constructor in your model. It will initialize default values once new instance is created. If user provides that fields, then it will be overridden. If no, value from constructor will be passed to EF.
What you are trying to do now, won't work according to specifications: https://msdn.microsoft.com/en-us/library/ms187872.aspx
Here you can see how to achieve what you want, considering that this field will always be generate in database.
This is one of the many reasons not to use entity models as viewmodels. MVC doesn't care that the required field has a default value, that information is database-related and not related to input validation.
Introduce a viewmodel where those properties are not required, and map the posted viewmodel to your entity model.
So, given an entity model that looks like this:
public class SomeEntity
{
// this property is not-nullable in the database
[Required]
public string SomeRequiredDatabaseField { get; set; }
}
Because the SomeRequiredDatabaseField is NOT NULL, it is annotated as such by Entity Framework, even if it has a default value. MVC will pick up this annotation, and consider the model not valid when the property has no value.
Now if you introduce a viewmodel, you can tell MVC that this property is not required:
public class SomeViewModel
{
// Not required
public string SomeRequiredDatabaseField { get; set; }
}
Now in your controller, you map the viewmodel to the entity model (preferably using AutoMapper):
public ActionResult Post(SomeViewModel model)
{
if (ModelState.IsValid)
{
var entityToSave = new SomeEntity
{
SomeRequiredDatabaseField = model.SomeRequiredDatabaseField
};
db.SomeEntity.Add(entityToSave);
}
// ...
}

SQL Server Session Serialization in ASP.Net MVC

I am new to ASP.Net MVC . Any help is greatly appreciated in resolving my problem.
I am using a LINQToSQL db in my MVC application. For one of the auto generated partial class (Example MyClass assume for table MyClass) , I created another Partial class as MyClass and added DataAnnotations Like following...
namespcae NP
{
[MetadaType(typeof(myData))]
[Serializable()]
public partial class MyClass
{
}
public myData
{
[Required]
public string ID { get ; set ;}
// Other properties are listed here
}
}
In my controller class example MyHomeController
I have a code as follows:
List<MyClass> list = new List<MyClass>();
list = dbContext.StoredProcedure(null).ToList<MyClass>()
session["data"] = list.
above code works fine if I use inProc session state. But if I use SQLServer mode then I get error as
"Unable to serialize the session state. In 'StateServer' and
'SQLServer' mode, ASP.NET will serialize the session state objects,
and as a result non-serializable objects or MarshalByRef objects are
not permitted. The same restriction applies if similar serialization
is done by the custom session state store in 'Custom' mode. "
Can anyone tell me what I am doing wrong here..?. I can see the data is getting populated in ASPState database tables. By application throws error as follows.
Just mark as Serializable all classes whose instances you want to store in Session.
Finally I was able to resolve the issue.
Solution:
Add the below statement before querying the database. In my case I was calling LinqToSQl context( dbContext).
dbContext.ObjectTrackingEnabled = false;
Sample Code:
List empList = new List();
dbContext.ObjectTrackingEnabled = false;
empList = dbContext.SomeStoredProcedure().ToList()
Session["employee"] = empList.

Parameter must be an entity type exposed by the DomainService?

Trying to implement a domain service in a SL app and getting the following error:
Parameter 'spFolderCreate' of domain method 'CreateSharePointFolder' must be an entity type exposed by the DomainService.
[EnableClientAccess()]
public class FileUploadService : DomainService
{
public void CreateSharePointFolder(SharePointFolderCreate spFolderCreate)
{
SharePointFolder spf = new SharePointFolder();
spf.CreateFolder_ClientOM(spFolderCreate.listName, spFolderCreate.fileName);
}
[OperationContract]
void CreateSharePointFolder(SharePointFolderCreate spFolderCreate);
[DataContract]
public class SharePointFolderCreate
{
private string m_listName;
private string m_fileName;
[DataMember]
public string listName
{
get { return m_listName; }
set { m_listName = value; }
}
[DataMember]
public string fileName
{
get { return m_fileName; }
set { m_fileName = value; }
}
}
So am I missing something simple here to make this all work?
It may be that the framework is inferring the intended operation because you have the word "Create" prefixing the function name (CreateSharePointFolder). Details of this behaviour can be found here
Although that is all fine for DomainServices and EntityFramework, following the information in that article, it can be inferred that methods beginning "Delete" will be performing a delete of an entity, so must accept an entity as a parameter. The same is true for "Create" or "Insert" prefixed methods. Only "Get" or "Select" methods can take non-entity parameters, making it possible to pass a numeric id (for example) to a "Get" method.
Try changing your method name temporarily to "BlahSharePointFolder" to see if it is this convention of inferrance that's causing your problem.
Also, as there is no metadata defined for your SharePointFolderCreate DC, you might need to decorate the class (in addition to the [DataContract] attribute) with the [MetadataType] attribute. You will see how to implement this if you used the DomainServiceClass wizard and point to an EF model. There is a checkbox at the bottom for generating metadata. Somewhere in your solution.Web project you should find a domainservice.metadata.cs file. In this file, you will find examples of how to use the [MetadataType] attribute.
For the RIA WCF service to work correctly with your own methods, you need to ensure that all entities existing on the parameter list have at least one member with a [Key] attribute defined in their metadata class, and that the entity is returned somewhere on your DomainService in a "Get" method.
HTH
Lee

Is it possible to map a table name for a domain object dynamically in grails?

I have a domain that looks something like
class Foo {
String name
static mapping = {
table 'foo'
}
}
but I want to make is more like :
static mapping = {
table "foo_${dynamicVarThatComesFromRequest}"
}
What I want to know is whether this is even possible?
Thanks!
It is possible. You can add a Hibernate interceptor to process all SQL statements and parse/replace some token in the table name you enter in the mapping with the actual table name you want to use.
src/groovy/DynamicTableNameInterceptor.groovy :
import org.hibernate.EmptyInterceptor
public class DynamicTableNameInterceptor extends EmptyInterceptor {
public String onPrepareStatement(String sql) {
// some kind of replacement logic here
def schema=SomeHelperClass.resolveSchema()
return sql.replaceAll('_SCHEMA_', schema)
}
}
grails-app/conf/spring/resources.groovy:
beans = {
// This is for Grails 1.3.x , in previous versions, the bean name is eventTriggeringInterceptor
entityInterceptor(DynamicTableNameInterceptor)
}
I don't think that's possible. Upon application startup, the mapping closure is evaluated and Hibernate mapping are generated as a result. This happens once upon startup, so dynamic resolution will not occur.
Something comparable is done in the multi-tenant-core plugin, using the 'single tenant' setup, you have a seperate database for each tenant.

Initializing DTOs on the server-side when using RIA services

Say you have an domain entity with business logic for initializing its default values. E.g.
class User : IUser, Entity
{
public User()
{
StartDate = DateTime.Now;
EndDate = StartDate.AddDays(3); // This value could be user-configured.
}
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
Using RIA services, the DTO that will be generated of course does not include any logic, only public properties. Which means that when a client (e.g. Silverlight application) displays a 'create new user' dialog, it will not be able to populate the fields with any default values (without, of course, duplicating the business logic on the client).
In an attempt to achieve this, I created new DTO (UserDTO) and a query in my UserDomainService:
// Construct a new domain entity and then convert to DTO
public UserDTO CreateNewUser()
{
var user = new User(); // Business logic has now been executed.
return new UserDTO(user);
}
This does allow the client to populate fields with default values, however when it comes time to add the newly created user, RIA has already added the UserDTO to it's internally mainted collection of entities, so you cannot call .Add on your domain context. You can still just call SubmitChanges, which will trigger the [Update] method to be called, however this seems to be going against the grain of how RIA services is supposed to be used (i.e. you shouldn't be doing an INSERT operation in an UPDATE method).
Is this scenario (i.e. server-side creation of DTOs) achievable in RIA services?
I don't know what your business logic looks like, but if you used a common method to save objects (whether new or modified) on the server, than you would be able to differentiate within that method, whether it is a modified object or really a new one.
Example on the server:
[Insert]
public void InsertUser(UserDTO user)
{
this.SaveUser(user);
}
[Update]
public void UpdateUser(UserDTO user)
{
this.SaveUser(user);
}
You could add a property to your User (or the base class, if you have one):
public class UserDTO
{
[...]
// only set this within the constructor,
// unfortunately it cannot be "private set", because of RIA Services
public bool IsNewEntity { get; set; }
}
In your SaveUser method use that flag:
private void SaveUser(UserDTO user)
{
if (user.IsNewEntity)
{
// do something with a new user
}
else
{
// do something with an existing user
}
}
The Constructor for the UserDTO would then be:
public UserDTO()
{
this.IsNewEntity = true;
}
I know, this looks a little trivial, but I do not know of a more "elegant" way.

Resources