How to get the DropDown selected value in controller in MVC3? - asp.net-mvc-3

Hi all i have to get the selected value from dropdown into my post method in controller ..how can i do this
here is my controller
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult AddNew()
{
ViewBag.Roles = new SelectList(List(), "RoleID", "RoleName");
return View();
}
//
//Geting All Roles In a GetRoles()/
//
public List<ResourceModel> List()
{
var roles = new List<ResourceModel>();
SqlConnection conn = new SqlConnection("Data Source=LMIT-0039;Initial Catalog=BugTracker;Integrated Security=True");
SqlCommand Cmd = new SqlCommand("Select GroupId,EmplopyeeRole from EmployeeGroup", conn);
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(Cmd);
DataSet ds = new DataSet();
da.Fill(ds);
for (int i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
var model = new ResourceModel();
model.RoleId = Convert.ToInt16(ds.Tables[0].Rows[i]["GroupId"]);
model.RoleName = ds.Tables[0].Rows[i]["EmplopyeeRole"].ToString();
roles.Add(model);
}
conn.Close();
return roles ;
}
//
//To perform the AddNew Logic..i.e it adds a new employee to DB/
//
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddNew(ResourceModel model)
{
// var modelList = new List<ProjectModel>();
using (SqlConnection conn = new SqlConnection("Data Source=LMIT-0039;Initial Catalog=BugTracker;Integrated Security=True"))
{
conn.Open();
SqlCommand insertcommande = new SqlCommand("InsertEmplyoee", conn);
insertcommande.CommandType = CommandType.StoredProcedure;
insertcommande.Parameters.Add("#EmployeeName", SqlDbType.VarChar).Value = model.EmployeeName;
insertcommande.Parameters.Add("#EmployeeEmailId", SqlDbType.VarChar).Value = model.EmployeeEmailId;
insertcommande.Parameters.Add("#EmployeePassword", SqlDbType.VarChar).Value = model.EmployeePassword;
insertcommande.Parameters.Add("#GroupName", SqlDbType.VarChar).Value = model.RoleName;
insertcommande.ExecuteNonQuery();
}
return View();
}
now i want to get the selected value #GroupName Parameter in my postmethod...can any one help how to do thi
this is my html
<%:Html.DropDownList("Roles")%>

You could have your POST action take a view model, or add another parameter to it that will hold the selected value:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddNew(ResourceModel model, string roles)
And don't forget to repopulate the ViewBag.Roles in your POST action the same way you did in your GET action if you intend to redisplay the same view.

You could use Request.Form["Roles"] in your controller action.. but maybe a better solution is creating a new view model for the page and you can use Html.DropDownListFor(m => m.RoleID, rolesSelectList) or whatever.. and the value will be automatically bound to your model in the udpate method:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddNew(ResourceModel model)

Related

How to register a new user in ASP.NET MVC application by passing the data into a Web API?

In my ASP.NET MVC 5 application, I want to make the Admin User add a new user. Upon signing in, the registration form fields (registration view) with new user values are captured in AccountController of the ASP.NET MVC 5 application as follows, and which then calls the API and the data must be transferred there:
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Register(AccountRegistration register)
{
string baseAddress = ConfigurationManager.AppSettings["ApiBaseUrl"];
//var client = new HttpClient();
//client.BaseAddress = new Uri("api/Account/Register");
//client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
string accessToken = this.ControllerContext.HttpContext.Request.Cookies["auth_key"].Values["token"];
using (var client = new HttpClient())
{
var form = new Dictionary<string, string>
{
{ "firstname", register.FirstName.Trim()},
{ "lastname", register.LastName.Trim()},
{ "email", register.Email.Trim()},
{ "phone", register.PhoneNo.Trim()},
{ "password", register.Password.Trim()},
};
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
var res = client.PostAsync(baseAddress + "/api/Account/Register", new StringContent(JsonConvert.SerializeObject(register), Encoding.UTF8, "application/json"));
res.Wait();
var taskResponse = res.Result;
var data = taskResponse.Content.ReadAsAsync<object>(new[] { new JsonMediaTypeFormatter() }).Result;
}
return View();
}
Here is my Web API AccountController code:
[HttpPost]
public IHttpActionResult Register([FromBody]UserRegister register)
{
DBAccess dblayer = new DBAccess();
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
UserManager<IdentityUser> _manager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(new TachusApi.DBContext.AuthDbContext()));
string pHash = _manager.PasswordHasher.HashPassword(register.Password);
dblayer.SaveAdmin(register, pHash);
return Ok("Success");
}
catch (Exception)
{
return Ok("Something went wrong.");
}
}
And here is the DBAccess.cs method which is called from this API's Register method to actually save the data into the database.
#region Save Admin
public void SaveAdmin(UserRegister user, string passwordHash)
{
SqlConnection conn = null;
SqlCommand command = null;
int retValue;
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
command = conn.CreateCommand();
command.CommandText = "Sp_Add_Admin";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#Email", user.Email);
command.Parameters.AddWithValue("#PasswordHash", passwordHash);
command.Parameters.AddWithValue("#FirstName", user.FirstName);
command.Parameters.AddWithValue("#LastName", user.LastName);
command.Parameters.AddWithValue("#PhoneNumber", user.PhoneNumber);
conn.Open();
command.ExecuteNonQuery();
conn.Close();
}
#endregion
My problem is that I have all the values of Register.cshtml (User Registration View) available on both the Register and SaveAdmin methods of the API except the phone number. I think I have some ambiguity in the model classes that I have created. I want the data to be stored in the database using a stored procedure I created.
When I run the code and the API is called, I am getting exception. Is there any one who can suggest me the best way to manage my code so that I can save the data into the database?

Load Database Values in Ajax Cascading DropDown

This is the first time I have used Ajax, and this is also my first C#.NET project, so I am very new. I am using .NET 4.0.
I have succesfully implemented the Ajax cascading dropdown, and upon submit, the data is stored in the database. However, this page also has an "Edit" feature, meaning if there is a value for said dropdown already populated in the database, it "should" display, and allow the user to change it. This is where I get stuck. If there is already a value for these dropdowns in the db, how can I display that?
I do have a try/catch for my other non-Ajax fields, and I have tried that on these, to no avail. I'll list that as well.
Code Behind:
public partial class Research : System.Web.UI.Page
{
//Page Load
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
/Create data table to populate fields with values from the selected record.
DataTable dt = new DataTable();
dt = selectDetails();
//Call Try/Catch Blocks to load fields.
tryRootCauseCategoryDD(cboRootCauseCategory, dt.Rows[0]["rootCauseCategory"].ToString());
tryRootCauseDD(cboRootCause, dt.Rows[0]["rootCause"].ToString());
}
}
protected void tryRootCauseCategoryDD(DropDownList cboRootCauseCategory, string ddSelected)
{
try
{
cboRootCauseCategory.SelectedValue = ddSelected;
}
catch
{
cboRootCauseCategory.SelectedIndex = 0;
}
}
protected void tryRootCauseDD(DropDownList cboRootCause, string ddSelected)
{
try
{
cboRootCause.SelectedValue = ddSelected;
}
catch
{
cboRootCause.SelectedIndex = 0;
}
}
protected DataTable selectDetails()
{
DataTable dt = new DataTable();
dt = dataAccess.ExecuteDataTable
(
"spRecordDetails", dataAccess.DEV, new SqlParameter[1]
{
new SqlParameter ("#vRecID", Request.QueryString["recID"].ToString())
}
);
return dt;
}
ASPX:
<asp:DropDownList ID="cboRootCauseCategory" runat="server"></asp:DropDownList>
<ajaxToolkit:CascadingDropDown ID="ccdRootCauseCategory" runat="server" Category="RootCauseCategory"
TargetControlID="cboRootCauseCategory" PromptText="(Please select:)" LoadingText="Loading.."
ServiceMethod="BindRootCauseCategoryDetails" ServicePath="CascadingDropDown.asmx">
</ajaxToolkit:CascadingDropDown>
<asp:DropDownList ID="cboRootCause" runat="server"></asp:DropDownList>
<ajaxToolkit:CascadingDropDown ID="ccdRootCause" runat="server" Category="RootCause" ParentControlID="cboRootCauseCategory"
TargetControlID="cboRootCause" PromptText="(Please select:)" LoadingText="Loading.."
ServiceMethod="BindRootCauseDetails" ServicePath="CascadingDropDown.asmx">
</ajaxToolkit:CascadingDropDown>
Web Service:
[WebService(Namespace = "http://microsoft.com/webservices/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
//To allow this Web Service to be called from script, using ASP.NET AJAX.
[System.Web.Script.Services.ScriptService()]
public class CascadingDropDown : System.Web.Services.WebService
{
//Database connection string
//private static string strconnection = ConfigurationManager.AppSettings["DEV"].ToString();
private static string strconnection = System.Configuration.ConfigurationManager.ConnectionStrings["DEV"].ConnectionString;
//database connection
SqlConnection conCategory = new SqlConnection(strconnection);
public CascadingDropDown()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}
/// WebMethod to Populate Root Cause Category Dropdown
[WebMethod]
public CascadingDropDownNameValue[] BindRootCauseCategoryDetails(string knownCategoryValues, string category)
{
conCategory.Open();
SqlCommand cmdRootCauseCategory = new SqlCommand
("Select Distinct RootCauseCategory From RootCause", conCategory);
cmdRootCauseCategory.ExecuteNonQuery();
SqlDataAdapter daRootCauseCategory = new SqlDataAdapter(cmdRootCauseCategory);
DataSet dsRootCauseCategory = new DataSet();
daRootCauseCategory.Fill(dsRootCauseCategory);
conCategory.Close();
//create list and add items in it by looping through dataset table
List<CascadingDropDownNameValue> RootCauseCategoryDetails = new List<CascadingDropDownNameValue>();
foreach (DataRow dtrow in dsRootCauseCategory.Tables[0].Rows)
{
//string recID = dtrow["recID"].ToString();
string RootCauseCategory = dtrow["RootCauseCategory"].ToString();
string RootCauseCategoryValue = dtrow["RootCauseCategory"].ToString();
RootCauseCategoryDetails.Add(new CascadingDropDownNameValue(RootCauseCategory,RootCauseCategoryValue));
}
return RootCauseCategoryDetails.ToArray();
}
/// WebMethod to Populate Root Cause Dropdown
[WebMethod]
public CascadingDropDownNameValue[] BindRootCauseDetails(string knownCategoryValues, string category)
{
string rootCauseCategory;
//This method will return a StringDictionary containing the name/value pairs of the currently selected values
StringDictionary rootCauseCategoryDetails = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
rootCauseCategory = (rootCauseCategoryDetails["RootCauseCategory"]);
conCategory.Open();
SqlCommand cmdRootCause = new SqlCommand("select recID, rootCause from RootCause where rootCauseCategory= #vRootCauseCategory", conCategory);
cmdRootCause.Parameters.AddWithValue("#vRootCauseCategory", rootCauseCategory);
cmdRootCause.ExecuteNonQuery();
SqlDataAdapter daRootCause = new SqlDataAdapter(cmdRootCause);
DataSet dsRootCause = new DataSet();
daRootCause.Fill(dsRootCause);
conCategory.Close();
//create list and add items in it by looping through dataset table
List<CascadingDropDownNameValue> rootCauseDetails = new List<CascadingDropDownNameValue>();
foreach (DataRow dtrow in dsRootCause.Tables[0].Rows)
{
string recID = dtrow["recID"].ToString();
string rootCause = dtrow["rootCause"].ToString();
rootCauseDetails.Add(new CascadingDropDownNameValue(rootCause, recID));
}
return rootCauseDetails.ToArray();
}
}
I decided to scrap the idea of a web service, and opted for an updatepanel instead. There is likely a less redundant way to do this, but it's working.
Final Solution:
Markup page:
<asp:TableCell Width="500">
<asp:UpdatePanel ID="UpdatePanel" runat="server">
<ContentTemplate>
<p><asp:DropDownList ID="cboRootCauseCategory" runat="server" AutoPostBack="True" onselectedindexchanged="cboRootCauseCategory_SelectedIndexChanged"></asp:DropDownList>
<asp:DropDownList ID="cboRootCause" runat="server" AutoPostBack="true"></asp:DropDownList></p>
</ContentTemplate>
</asp:UpdatePanel>
</asp:TableCell>
Code Behind:
if (!IsPostBack)
{
//Create data table to populate fields with values from the selected record.
DataTable dt = new DataTable();
dt = selectDetails();
//Call Try/Catch Blocks to load fields.
tryRootCauseCategoryDD(cboRootCauseCategory, dt.Rows[0]["rootCauseCategory"].ToString());
tryRootCauseDD(cboRootCause, dt.Rows[0]["rootCause"].ToString());
}
protected void tryRootCauseCategoryDD(DropDownList cboRootCauseCategory, string ddSelected)
{
try
{
//Load Root Cause Category Drop Down
DataTable RootCauseCategories = new DataTable();
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DEV"].ConnectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter("Select recID, rootCauseCategory From RootCauseCategory", con);
adapter.Fill(RootCauseCategories);
cboRootCauseCategory.DataSource = RootCauseCategories;
cboRootCauseCategory.DataTextField = "RootCauseCategory";
cboRootCauseCategory.DataValueField = "recID";
cboRootCauseCategory.DataBind();
}
cboRootCauseCategory.Items.Insert(0, new ListItem("(Please select:)", "0"));
cboRootCauseCategory.SelectedValue = ddSelected;
}
catch
{
//Load Root Cause Category Drop Down
DataTable RootCauseCategories = new DataTable();
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DEV"].ConnectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter("Select recID, rootCauseCategory From RootCauseCategory", con);
adapter.Fill(RootCauseCategories);
cboRootCauseCategory.DataSource = RootCauseCategories;
cboRootCauseCategory.DataTextField = "RootCauseCategory";
cboRootCauseCategory.DataValueField = "recID";
cboRootCauseCategory.DataBind();
}
cboRootCauseCategory.Items.Insert(0, new ListItem("(Please select:)", "0"));
cboRootCauseCategory.SelectedIndex = 0;
}
}
protected void tryRootCauseDD(DropDownList cboRootCause, string ddSelected)
{
try
{
string cboRootCauseCategoryID = Convert.ToString(cboRootCauseCategory.SelectedValue);
DataTable RootCauses = new DataTable();
using (SqlConnection con2 = new SqlConnection(ConfigurationManager.ConnectionStrings["DEV"].ConnectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter("Select recID, rootCause, rootCauseCategory From RootCause Where rootCauseCategory = '" + cboRootCauseCategoryID + "'", con2);
adapter.Fill(RootCauses);
cboRootCause.DataSource = RootCauses;
cboRootCause.DataTextField = "RootCause";
cboRootCause.DataValueField = "recID";
cboRootCause.DataBind();
}
cboRootCause.SelectedValue = ddSelected;
}
catch
{
cboRootCause.SelectedIndex = 0;
}
}
protected void cboRootCauseCategory_SelectedIndexChanged(object sender, EventArgs e)
{
string cboRootCauseCategoryID = Convert.ToString(cboRootCauseCategory.SelectedValue);
DataTable RootCauses = new DataTable();
using (SqlConnection con2 = new SqlConnection(ConfigurationManager.ConnectionStrings["DEV"].ConnectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter("Select recID, rootCause, rootCauseCategory From RootCause Where rootCauseCategory = '" + cboRootCauseCategoryID + "'", con2);
adapter.Fill(RootCauses);
cboRootCause.DataSource = RootCauses;
cboRootCause.DataTextField = "RootCause";
cboRootCause.DataValueField = "recID";
cboRootCause.DataBind();
}
cboRootCause.Items.Insert(0, new ListItem("(Please select:)", "0"));

download pdf files stored in database in mvc3

I store few pdf files in my db as binary format using the below code in my controller,
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
Image newImage = new Image();
newImage.MimeType = file.ContentType;
var binaryReader = new BinaryReader(file.InputStream);
newImage.Data = binaryReader.ReadBytes(file.ContentLength);
binaryReader.Close();
objImage.InsertImage(newImage.Data);
return View();
}
now i want to download them back based on the id passed to the contrller that pdf files should be downloaded??
this is my code for pdf download, wat do i need to add more
public ActionResult Download(int id)
{
DataSet da = new DataSet();
da = objImage.getUserImage(id);
DataTable dt = new DataTable();
dt = da.Tables[0];
Byte[] imagedata=(Byte[])dt.Rows[0]["UsImage"];
}
this is my code for pdf download, wat do i need to add more
Return an ActionResult:
public ActionResult Download(int id)
{
...
byte[] imagedata = (byte[])dt.Rows[0]["UsImage"];
return File(imagedata, "image/png");
}
and if you want the browser to popup a Save As dialog instead of displaying the image inline specify a filename:
public ActionResult Download(int id)
{
...
byte[] imagedata = (byte[])dt.Rows[0]["UsImage"];
return File(imagedata, "image/png", "foo.png");
}
Obviously the MIME type and the filename could come from your database as well. In this example I have hardcoded them but you could adapt this code.
return File(result.Content, result.Extension.Replace(".", ""));
public ActionResult Download(int id)
{
DataSet da = new DataSet();
da = objImage.getUserImage(id);
DataTable dt = new DataTable();
dt = da.Tables[0];
Byte[] imagedata=(Byte[])dt.Rows[0]["UsImage"];
return File(imagedata, "image/png");
}
public ActionResult GetPdf(int id)
{
ProjectProfile projectprofile = db.ProjectProfiles.Find(id);
var image = projectprofile.pdf;
return File(image, "application/pdf");
}

i have Webgrid in razor engine when i perform grid function grid is postbacking to first page

I have webgrid in Razor engine. When I perform edit function, grid is coming back to grid pageone, how can I restrict the grid to stay back in same page of grid when we perform any grid functionality?
public class PeopleListController : Controller
{
//sample data source
public List Persons
{
get {
return new List {
new Person {ID=1, Birthday=DateTime.Now, Name="John"},
new Person {ID=2, Birthday=DateTime.Now, Name="Paul"},
new Person {ID=3, Birthday=DateTime.Now, Name="Jane"},
new Person {ID=4, Birthday=DateTime.Now, Name="Trisha"},
new Person {ID=5, Birthday=DateTime.Now, Name="Kevin"},
new Person {ID=6, Birthday=DateTime.Now, Name="Janice"},
new Person {ID=7, Birthday=DateTime.Now, Name="Dennis"},
new Person {ID=8, Birthday=DateTime.Now, Name="Jack"},
new Person {ID=9, Birthday=DateTime.Now, Name="Trevor"},
new Person {ID=10, Birthday=DateTime.Now, Name="Michael"},
new Person {ID=11, Birthday=DateTime.Now, Name="Sean"},
new Person {ID=12, Birthday=DateTime.Now, Name="Emerson"},
new Person {ID=13, Birthday=DateTime.Now, Name="Jay"},
new Person {ID=14, Birthday=DateTime.Now, Name="Henry"},
new Person {ID=15, Birthday=DateTime.Now, Name="Luke"}
};
}
}
public ActionResult Index()
{
//get grid parameters from URL/POST (if any)
var gridParameters = GridParameters.GetGridParameters();
//get data
var data = GetDataUsingLINQ(gridParameters.Sort, //order by column
gridParameters.SortDirection, //order by direction
gridParameters.Page ?? 1, //returned page
5); //displayed rows per page
//set record count for use in view
ViewBag.GridRecordCount = Persons.Count;
return View(data);
}
//get data from datasource using LINQ (sample data access layer)
private IEnumerable<Person> GetDataUsingLINQ(string sort, string sortDir, int page, int numRows)
{
if (!string.IsNullOrEmpty(sort))
return Persons.AsQueryable().OrderBy(sort + " " + sortDir).Skip((page - 1) * numRows).Take(numRows).ToList();
else
return Persons.AsQueryable().Skip((page - 1) * numRows).Take(numRows).ToList();
}
//get data from datasource using SPROC (sample data access layer)
private IEnumerable<Person> GetDataUsingSPROC(string sort, string sortDir, int? page, int numRows)
{
//note: I did not use EF nor LINQ to SQL in the example below as I do
// not know any clean/elegant way of calling stored using those two
//note: server side paging and sorting SP implementation is not included, there are lots of articles on the web that discuss about it.
// You can google "sql server side paging sorting"
var sqlCon = new SqlConnection("<insert your connection string here>");
sqlCon.Open();
var sqlCmd = new SqlCommand();
sqlCmd.CommandType = System.Data.CommandType.StoredProcedure;
sqlCmd.CommandText = "<insert your SP name here>";
sqlCmd.Connection = sqlCon;
sqlCmd.Parameters.AddWithValue("#Sort", sort);
sqlCmd.Parameters.AddWithValue("#SortDirection", sortDir);
sqlCmd.Parameters.AddWithValue("#Page", page);
sqlCmd.Parameters.AddWithValue("#NumRows", numRows);
var list = new List<Person>();
using(SqlDataReader reader = sqlCmd.ExecuteReader())
{
while (reader.Read())
{
var p = new Person();
p.ID = Convert.ToInt32(reader["ID"]);
p.Name = reader["Name"].ToString();
p.Birthday = Convert.ToDateTime(reader["Birthday"]);
list.Add(p);
}
}
sqlCon.Close();
return list;
}
}

Is there some way to clean up this controller code?

Most of the code I see online on MVC3 has very little code in the controller, but I can't seem to figure out how to make this code more streamlined.
Maybe if you take a look at it you can suggest improvements. If you need to see my UserModel class, let me know.
Here's the code for the Account controller.
namespace WebUI.Controllers
{
public class AccountController : Controller
{
public ActionResult Register()
{
UserModel model = new UserModel();
EFCityRepository cityRepo = new EFCityRepository();
model.Cities = new List<SelectListItem>();
foreach (var city in cityRepo.FindAllCities()) {
model.Cities.Add(new SelectListItem { Text = city.Name, Value = city.CityId.ToString(), Selected = true });
}
EFGenderRepository genderRepo = new EFGenderRepository();
model.Genders = new List<SelectListItem>();
foreach (var gender in genderRepo.FindAllGenders()) {
model.Genders.Add(new SelectListItem { Text = gender.Name, Value = gender.GenderId.ToString(), Selected = true });
}
return View(model);
}
[HttpPost]
public ActionResult Register(UserModel model)
{
EFCityRepository cityRepo = new EFCityRepository();
model.Cities = new List<SelectListItem>();
foreach (var city in cityRepo.FindAllCities())
{
model.Cities.Add(new SelectListItem { Text = city.Name, Value = city.CityId.ToString(), Selected = true });
}
EFGenderRepository genderRepo = new EFGenderRepository();
model.Genders = new List<SelectListItem>();
foreach (var gender in genderRepo.FindAllGenders())
{
model.Genders.Add(new SelectListItem { Text = gender.Name, Value = gender.GenderId.ToString(), Selected = true });
}
if (ModelState.IsValid)
{
Domain.User user = new Domain.User();
user.UserRoleId = 1;
user.Nickname = model.Nickname;
user.Name = model.Name;
user.Lastname = model.Lastname;
user.GenderId = model.GenderId;
user.Address = model.Address;
user.Email = model.Email;
user.Telephone = model.Telephone;
user.MobilePhone = model.MobilePhone;
user.Carnet = model.Carnet;
user.DateOfBirth = model.DateOfBirth;
user.DateOfRegistry = DateTime.Now;
user.LastDateLogin = DateTime.Now;
user.IsActive = false;
user.LanceCreditBalance = 5;
user.LancesSpent = 0;
user.Login = model.Login;
user.Password = model.Password;
user.EmailVerificationCode = "TempTokenString";
user.CityId = model.CityId;
EFUserRepository repo = new EFUserRepository();
var result = repo.CreateUser(user);
if (result == UserCreationResults.Ok)
{
FormsAuthentication.SetAuthCookie(model.Nickname, false /* createPersistentCookie */);
return RedirectToAction("Index", "Home");
}
else
{
switch (result)
{
case UserCreationResults.UsernameExists:
ModelState.AddModelError("", "El nombre de usuario ya esta siendo utilizado.");
break;
case UserCreationResults.EmailAlreadyExists:
ModelState.AddModelError("", "Ese correo ya esta en uso.");
break;
case UserCreationResults.NicknameAlreadyExists:
ModelState.AddModelError("", "El nickname ya esta siendo utilizado.");
break;
case UserCreationResults.UnknownError:
ModelState.AddModelError("", "Algo durante el registro. Por favor intente de nuevo.");
break;
default:
break;
}
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
}
}
I'm using Entity Framework as my ORM, it generates a User class automatically for me. However, I made a User*Model* class so I could add data annotations for the views to use. Maybe this is the wrong idea?
I have many suggestions. For startes, read up about Dependancy Injection and Inversion of Control (DI and IoC). They will make all that boilerplate object instantiation a thing of the past.
Next, convert those for-each list builders into Linq expressions. Much more succinct and more likely faster as well.
Then, in your post handler, again do the same things there. In addition, get to know AutoMapper, which will automatically map your view to domain classes and make your life much easier.
If you did those things, your code would be reduced by 2x, maybe even 3.
EDIT:
An example linq query, because I really don't know the definition of your objects... would look something like this:
model.Cities = cityRepo.FindAllCities().Select(city => new SelectListItem() {
Text = city.Name, Value = city.CityId.ToString()}).ToList();
Notice how you don't have to new up a new List, since that's returned by the ToList() method. It is also using projection to select the items into a new SelectListItem.
Basically, you could write your method like this, using Dependancy Injection, Linq, and AutoMapper (it looks longer because i had to break lines multiple times to fit the small viewing are of SO):
namespace WebUI.Controllers
{
public class AccountController : Controller
{
private IGenderRepository _genderRepo;
private ICityrRepository _cityRepo;
private IUserRepository _userRepo;
public AccountController(IGenderRepository gr, ICityRepository cr,
IUserRepository ur)
{
_genderRepo = gr;
_cityRepo = cr;
_userRepo = ur;
}
public ActionResult Register()
{
UserModel model = new UserModel();
// Selected property is ignored by MVC on SelectListItems
model.Cities = _cityRepo.FindAllCities().Select(city =>
new SelectListItem() { Text = city.Name,
Value = city.CityId.ToString()}).ToList();
model.Genders = _genderRepo.FindAllGenders().Select(gender =>
new SelectListItem() { Text = gender.Name,
Value = gender.GenderId.ToString()}).ToList();
return View(model);
}
[HttpPost]
public ActionResult Register(UserModel model)
{
model.Cities = _cityRepo.FindAllCities().Select(city =>
new SelectListItem() { Text = city.Name,
Value = city.CityId.ToString()}).ToList();
model.Genders = _genderRepo.FindAllGenders().Select(gender =>
new SelectListItem() { Text = gender.Name,
Value = gender.GenderId.ToString()}).ToList();
if (ModelState.IsValid)
{
Domain.User user = Mapper.Map<Domain.User, Model>(model)
var result = _userRepo.CreateUser(user);
if (result == UserCreationResults.Ok) {
FormsAuthentication.SetAuthCookie(model.Nickname, false);
return RedirectToAction("Index", "Home");
} else {
ModelState.AddModelError("", GetErrorString(result));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
}
}
your Idea is good. Because it is not a good practice to have entity classes as the view models in MVC layer because it will create a tight coupling between your presentation and persistence logic.
To cleanup yuor code you can use AutoMapper ( http://automapper.codeplex.com/ ) to map your entity classes to view model easy without writing too many codes. http://jasona.wordpress.com/2010/02/05/getting-started-with-automapper/ here is a good article for you.

Resources