I am new to ASP.NET MVC Forms Authentication and have just started to create my own Custom Membership Provider. My ValidateUser and ChangePassword methods work but now I want to use the GetUser method to return the current user's data throughout my site. My AX method returns an AxaptaRecord which contains details of the user, like their phone number, company name etc.. How would I use this with the GetUser method?
You just need to create a new instance of MembershipUser object and populate properties from the AxaptaRecord object, here is some pseudocode:
MembershipUser user = new MembershipUser("AX",
(string)axRecord.get_Field("name"),
axRecord.get_Field("recid"),
email, //get this from SysUserInfo table
string.Empty,
string.Empty,
(bool)axRecord.get_Field("enable"),
!(bool)axRecord.get_Field("enable"),
(DateTime)Convert.ChangeType(axRecord.get_Field("createdDateTime"), typeof(DateTime)),
DateTime.MinValue,
DateTime.MinValue,
DateTime.MinValue,
DateTime.MinValue);
Then you return user from your GetUser method. See the GetUser method description here: http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx
Controller:
var userDetails = System.Web.Security.Membership.GetUser(username);
Then, there are many different ways for you to pass the data to View.
Each way has its advantage and disadvantage.
For details, please click here.
Model strongly-typed view can let you easily handle validation and generate data but not very good in display data if you have more than one table.
Related
I have an project that I have to do in mvc pattern. But I'm confused. If my model only contains method for manipulating the database and do not have any attribute, will that be the right way ?
For example, for login :
The model will have a method
static insertAccount(String username, String password) {
// the code to insert username and password to the database
}
And when the user push "submit", the form will pass the username and password to the controller, which has this method
createNewAccount(String username, String password) {
Model.insertAccount(username,password);
}
Your model should not contain methods to insert data. That should be abstracted out to the Data Access Layer of your application. The MVC pattern is for interacting with the UI.
The controller will pass data (a model) to be rendered. After some type of action, the view will pass data (a model) back to the controller.
From the controller, you can run some business logic, make calls to the data access layer, call another API. And, if nessecary, pass that model to the other layer.
Using ASP.NET MVC when I create my model, then a controller based on the model with CRUD operations, the CRUD views are generated. I added some code using Fluent API to require certain fields but for some reason the ModelState.IsValid passes even when these fields are not completed. What determines whether this passes or not? I thought it was based on your model property data types and other things like being required or maxlength, etc....
Also, I have manually added code to grab a list of Categories from the database and generate a checkbox for each one in the View. This is a navigation property for the Project model where there is a many-many relationship. To get the group of checked values in the Create(Project project) method in the controller I use:
var selected = Request["categories"].Split(',');
This however, throws the classic Object reference not set to an instance of an object error if no values are checked. So what I want to know is, how can I determine that this does not have any values so I can do something else once detected?
I added some code using Fluent API to require certain fields but for
some reason the ModelState.IsValid passes even when these fields are
not completed.
ASP.NET MVC doesn't know anything about the Fluent API of Entity Framework and doesn't evaluate this configuration. You only can use the data annotations which MVC will recognize:
[Required]
public string SomeProperty { get; set; }
...how can I determine that this does not have any values so I can do
something else once detected?
Not sure if I understand it correctly but I'd say:
var categories = Request["categories"];
if (categories != null)
{
var selected = categories.Split(',');
// ...
}
else
{
// do something else
}
i have a project that use MVC3. in my project, i have a page that user can edit their account (UserComment, UserEmail, IsLocked, IsApproved). i already make the View for Edit Account. i have some trouble to make the Edit Controller.
here's my code:
[HttpPost]
public ActionResult Edit(string id, FormCollection collection)
{
id = id.Replace("+", " ");
var user = Membership.GetUser();
Guid UserGUID = new Guid(user.ProviderUserKey.ToString());
var SysUser = db.System_User.Single(u => u.User_UserId == UserGUID);
//this is for updating User Office in my System_user table
SysUser.User_Office = collection["SysUsers[0].UserOffice"];
//this is for updating User Account in aspnet_membership table
user.UserName = collection["SysUsers[0].UserName"];
Membership.UpdateUser(user);
user.Comment = collection["SysUsers[0].UserComment"];
Membership.UpdateUser(user);
user.Email = collection["SysUsers[0].UserEmail"];
Membership.UpdateUser(user);
return View();
}
when i run my controller, i get some error like :
user.UserName is read only, i cant update this one.
i get user.Comment value, but its not update.
i get error in my Edit View, it says "Object reference not set to an instance of an object."
#using (Html.BeginForm("edit/" + #Model.SysUsers[0].UserID, "cpanel/sysuser", FormMethod.Post))
can anyone help me ?
thanks,
You cannot update the UserName of a user using ASP.NET Membership provider. You need to write some custom data access logic if you wish to update a username.
I would suggest using the Membership Provider primarily for authentication and build all the other maintenance etc. methods into your User's business objects.
MVC best practices state that the model should handle input/data validation. Let's say that we have a model that creates new user accounts, with the following fields and constraints:
Username - not null, not already in DB
Password - not null, alphanumeric only
E-mail - not null, not already in DB, valid e-mail format
We have an AccountModel with a CreateNewUser() function:
component
{
public void function CreateNewUser(string username, string password, string email)
{
// create account
}
}
Then we have a controller that processes a form post and tells the model to create the account:
component
{
public void function NewUser()
{
var username = event.getValue("username");
var password = event.getValue("password");
var email = event.getValue("email");
var accountModel = new AccountModel();
accountModel.CreateNewUser(username, password, email);
event.addResult("UserCreated");
}
Now I want to add validation. If the user fails to provide input for all three fields, the application should show the user three validation error messages. This is easy enough to do in the controller:
// assumes that ValidateInput() is a function on the controller that returns an array
var validationErrors = ValidateInput(username, password, email);
// if there were any validation errors, return a ValidationError result
if (len(validationErrors)
{
event.setValue("validationerrors", validationErrors);
event.addResult("ValidationError");
}
else
{
event.addResult("UserCreated");
}
And the view will pull the validationerrors variable and display the error messages.
However, this logic is supposed to reside in the model. How do I do this? I can think of two ways:
Method 1: Move ValidateInput() from the controller to the model. Now the controller has to call ValidateInput() first before CreateNewUser(). If the programmer forgets to do this, CreateNewUser() will throw a validation exception. The downside to this is that now every data operation that requires validation will need an if/else block.
Method 2: Forego having to call ValidateInput() and just call CreateNewUser() directly. If there were any validation errors, an exception will be thrown and it will contain the error message array. This method would work in C#, but it looks like ColdFusion does not support returning of data with the exception, only an exception message and type. Also, every data operation will require a try/catch block.
Method 3: ??
How would you handle validation in this case? Is method 1 what most people do when it comes to validation in the model? Or do people typically use method 2? Or is there a method 3 that I'm not thinking of?
I don't think you should couple the validation of the user's data entry to the creation of the user's account: they are too different things.
If you couple the two together, it means you're basically doing form validation every time you create an account, which doesn't seem right to me.
I see form validation as a UI concern, more than a concern of the objects that might be ultimately created from that data. Obviously your createNewUser() method has its own business rules (which will probably closely mirror that of the validation for a create-new-user form, but they are still separate concerns).
It is possibly a bit unorthodox, but I will put a validateUserData() (or something) method in my User CFC which the form-validation model then calls to help with the validation. This means the business rules for a user are in the same place, and can be called separately. Thereafter, createNewUser() works on a garbage-in/garbage-out principle.
Sidenote: createNewUser() is a bit of a tautological name, innit? What other sort of user would you be creating other than a new one? Also, if it's in your Account.cfc; is it a new user or a new account that's being created? If an account and a user are not synonymous and an account might exist without a user (or vice-versa), perhaps you ought to have a User.cfc too. Then again, this code you've given us could simply be for the purposes of illustration, and you've got all this covered.
I have a bunch of tables in my database that have a column which is of type GUID. I do not want this to be a part of scaffolding when i generate my views, so i am using [ScaffoldColumn(false)]. I don't want the user to enter an actual GUID when "creating" a new entity. Is there any way to automate the process of automatically adding a new GUID (thru data annotations or some other way??) when a user creates a new Entity or do i have to modify the controller for every table that has a GUID so that every time a user creates a new entry i make sure i generate a new GUID before saving it?
Thanks.
This is where (IMHO) the new scaffolding features encourages bad code.
You should define separate ViewModels for your views. These contain only the fields you wish the user to change along with any view specific validation/rules.
Within your controller action, you can check whether the user input is valid (ModelState.IsValid) and if so, do some lefty-righty mapping between your ViewModel properties and those of your entity.
See ViewModel Best Practices for more details.
However, to answer your question, you can use the HiddenInput attribute on an Id field so that it is rendered as a <input type="hidden"...
With regard with setting the Id, create a base class for your entities e.g:
public abstract class BaseEntity {
public Guid Id {get;set;}
public BaseEntity() {
Id = Guid.NewGuid();
}
}
You can then inherit your entities from this class and when you call new MyEntity() the base class constructor will be invoked, thus setting the Id.