New to MVC! I can pull data from my Database first Entity Framework model (emdx) just fine... Works Great - Coolest thing ever! But I have 2 questions:
1) I cannot get the data back to my view. (I want to display the security question (being returned from my stored proc in my DB First Entity Data Model - emdx) and allow the user to answer the question.
2) I also can't seem to redirect to a view in a different view folder (from the "View\Account" folder to the "View\Home" folder.
I'm pretty sure this is easy and I'm just missing something basic.
Here is my MVC controller code:
public ActionResult Login(LoginViewModel model, string returnUrl)
{
string strEncr = "";
try
{
if (ModelState.IsValid)
{
//Create Hash with Salt for For New PWs
strEncr = Helper.ComputeHash(model.Password, "SHA512", null);
string DBPW = "";
string encryptedPassword = "";
try
{
using (var context = new WMSEntities1())
{
encryptedPassword = context.users
.Where(u => u.emailAddress == model.Username)
.Select(u => u.password)
.SingleOrDefault();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//Test for match of PW between User and what's stored in DB
bool flag = Helper.VerifyHash(model.Password, "SHA512", encryptedPassword);
var loginInfo = databaseManager.LoginAndGetSecQuestion(model.Username, encryptedPassword).ToList();
// Verification.
if (loginInfo != null && loginInfo.Count() > 0)
{
// Initialization.
var logindetails = loginInfo.First();
// Login In.
this.SignInUser(logindetails.emailAddress, false);
ViewBag.SecurityQuestion = logindetails.securityQuestion;
// Info.
return View("~/Views/Home/Index.cshtml", loginInfo);
// return this.RedirectToLocal(returnUrl);
}
else
{
// Setting.
ModelState.AddModelError(string.Empty, "Invalid username or password.");
}
}
}
catch (Exception ex)
{
// Info
Console.Write(ex);
}
// If we got this far, something failed, redisplay form
return this.View(model);
}
Here is my code snipets in my view:
#*#model System.Data.DataSet*#
#model AodNetIntegration.LoginAndGetSecQuestion_Result
#{
ViewBag.Title = "Doc Center Login Screen";
}
#*<h2>#ViewBag.Title.</h2>http://asmak9.blogspot.com/2016/03/aspnet-mvc5-integrating-existing.html
<h3>#ViewBag.Message</h3>*#
#using (Html.BeginForm("LoginStage2", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<table cellspacing="5" style="width: 293px;">
<tr>
<td></td>
</tr>
<tr>
<td>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.LabelFor(m => m.securityQuestion, new { #class = "col-md-2 control-label, width= 50" })
#Html.DisplayFor(m => m.securityQuestion, new { #class = "col-md-2 control-label, width= 50" })
#Html.ValidationMessageFor(m => m.securityQuestion, "", new { #class = "text-danger" })<br />
#Html.LabelFor(m => m.securityQuestionAnswer, new { #class = "col-md-2 control-label" })
#Html.PasswordFor(m => m.securityQuestionAnswer, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.securityQuestionAnswer, "", new { #class = "text-danger" })
</td>
</tr>
<tr>
<td align="right" style="text-align: right;">
<input type="submit" value="Submit" class="btn btn-default" />
</td>
</tr>
</table>
Here is the error I get:
When it goes back to the Index page:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[AodNetIntegration.LoginAndGetSecQuestion_Result]', but this dictionary requires a model item of type 'AodNetIntegration.LoginAndGetSecQuestion_Result'.
Controller Model Method:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace AodNetIntegration
{
using System;
public partial class LoginAndGetSecQuestion_Result
{
public int userID { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string securityQuestion { get; set; }
public string emailAddress { get; set; }
public string securityQuestionAnswer { get; set; }
}
}
Thanks,
Your query (var loginInfo = databaseManager....) is returning a collection of LoginAndGetSecQuestion_Result, not a single object, and you then return that collection to the view using
return View("~/Views/Home/Index.cshtml", loginInfo);
but you view expects a single LoginAndGetSecQuestion_Result object, not a collection.
You code should be
return View("~/Views/Home/Index.cshtml", logindetails);
However you can simplify your code by modifying the query to return a single object and testing for null
var loginInfo = databaseManager.LoginAndGetSecQuestion(model.Username, encryptedPassword).FirstOrDefault();
if (loginInfo != null)
{
this.SignInUser(loginInfo.emailAddress, false);
ViewBag.SecurityQuestion = logindetails.securityQuestion;
return View("~/Views/Home/Index.cshtml", loginInfo);
}
else
{
ModelState.AddModelError(string.Empty, "Invalid username or password.");
}
Related
How can I send a single string value through view from in the WebAPI made in ASP.NET core.
Here is my API:
[HttpPost]
[Route("studentlogin/{value}")]
public IActionResult StudentLogin(string value)
{
string name = String.Concat(value.Where(s => !Char.IsWhiteSpace(s)));
name = name.ToLower();
var newStudent = new Student();
newStudent.FullName = name;
db.Entry(newStudent).State = EntityState.Added;
db.SaveChanges();
var selectStudent = db.Students.Where(ss => ss.FullName == name).FirstOrDefault();
var id = selectStudent.Id;
string idToString = id.ToString();
string answer = sha384converter(idToString);
selectStudent.HashId = answer;
db.Entry(selectStudent).State = EntityState.Modified;
db.SaveChanges();
return Ok();
}
I want to send paramenter value in it through View Forms, How can I send data in it?
Thanks in advance.
[Route("studentlogin/{value}")]
If you are using the above route, the request URL should like this: https://localhost:44310/api/apicontrollername/studentlogin/XXX, the parameter will be transferred from the URL and route.
to send paramenter value in it through View Forms, How can I send data
in it?
To send parameter value from posted form fields, you could modify the code as below:
In the API controller, remote the route parameter and add the FromForm attribute.
[HttpPost]
[Route("studentlogin")]
public IActionResult StudentLogin([FromForm]string value)
{
string name = "Default value";
if (!string.IsNullOrEmpty(value))
{
name = String.Concat(value.Where(s => !Char.IsWhiteSpace(s)));
}
... // add your code
return Ok(name);
}
Then, create a model which contain the value property, like this:
public class StudentLoginViewModel
{
public string value { get; set; }
}
In the View page, display the above model in the form:
#model WebApplication6.Models.StudentLoginViewModel;
<form id="myform">
<div class="form-group">
<label asp-for="value" class="control-label"></label>
<input asp-for="value" class="form-control" />
<span asp-validation-for="value" class="text-danger"></span>
</div>
<div class="form-group">
<input type="button" id="btnsubmit" value="Submit" class="btn btn-primary" />
</div>
</form>
and add the following script at the end of the above view page:
#section Scripts{
<script>
$(function () {
$("#btnsubmit").click(function () {
//use the serialize() method to encode a set of form elements as a string for submission
var data = $("#myform").serialize();
//you can also create JavaScript object and send the data.
//var data = { value: $("#value").val() };
$.ajax({
url: '/api/todo/studentlogin', // change the url to yours.
type: "post",
contentType: 'application/x-www-form-urlencoded',
data: data,
success: function (result) {
console.log(result);
}
});
});
})
</script>
}
The result as below:
I'm trying to make an Edit Form for IdentityRole. When the page is loaded I normaly receive the model with Id something like this "09e43076-c333-4145-bccb-8bc7f9db470e", but when the view is created I see that #Html.HiddenFor(m => m.Id) gets an old name value instead of Id (see screenshots in the links below). Why is it happening? Thanks!
GET: Edit
[HttpGet]
public ActionResult Edit(string id)
{
_context = new ApplicationDbContext();
if (User.Identity.IsAuthenticated)
{
if (!isAdminUser())
{
return RedirectToAction("Login", "Account");
}
}
else
{
return RedirectToAction("Login", "Account");
}
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
var role = roleManager.FindByName(id);
return View(role);
}
View: Edit
#model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
#{
ViewBag.Title = "Edit Role";
}
<h2>Edit User Role:</h2>
#section RolesCSS {
<link href="#Url.Content("~/Views/Role/style/style.css")" rel="stylesheet"/>
<div class="form-group">
#using (Html.BeginForm("Edit", "Role", FormMethod.Post, new { #class = "AddRoleForm" }))
{
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.Users)
<div class="Label">
<p>Edit New User Role Name:</p>
</div>
<div class="FormControl">
#Html.EditorFor(m => m.Name, new {htmlAttributes = new {#class = "form-control"}})
</div>
<div class="FormControl">
<input class="btn btn-default" type="submit" value="Edit Role"/>
</div>
}
</div>
}
screenshot of values received as model in the view
screenshot of the source of the rendered html
Despite I've found a solution I'm still interested what was wrong with the first aproach.
I've found a workaround here (the content/explanation is in russian lang)
I created a class EditRoleModel as a temporary model, to avoid the issue I was having before,
public class EditRoleModel
{
public string Id { get; set; }
public string Name { get; set; }
}
that I pass as a model to View:
[HttpGet]
public ActionResult Edit(string id)
{
_context = new ApplicationDbContext();
if (User.Identity.IsAuthenticated)
{
if (!isAdminUser())
{
return RedirectToAction("Login", "Account");
}
}
else
{
return RedirectToAction("Login", "Account");
}
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
var role = roleManager.FindByName(id);
var model = new EditRoleModel() {Id = role.Id, Name = role.Name};
return View(model);
}
then I slightly change the View to recieve model of type EditRoleModel:
#model WebUI.Models.EditRoleModel
#{
ViewBag.Title = "Edit Role";
}
<h2>Edit User Role:</h2>
#section RolesCSS {
<link href="#Url.Content("~/Views/Role/style/style.css")" rel="stylesheet"/>
<div class="form-group">
#using (Html.BeginForm("Edit", "Role", FormMethod.Post, new { #class = "AddRoleForm" }))
{
<div>#Model.Id</div>
#Html.HiddenFor(m => m.Id)
<div class="Label">
<p>Edit New User Role Name:</p>
</div>
<div class="FormControl">
#Html.EditorFor(m => m.Name, new {htmlAttributes = new {#class = "form-control"}})
</div>
<div class="FormControl">
<input class="btn btn-default" type="submit" value="Edit Role"/>
</div>
}
</div>
}
and finaly this is the controller where I update the IdentityRole:
[HttpPost]
public ActionResult Edit(EditRoleModel model)
{
_context = new ApplicationDbContext();
if (User.Identity.IsAuthenticated)
{
if (!isAdminUser())
{
return RedirectToAction("Login", "Account");
}
}
else
{
return RedirectToAction("Login", "Account");
}
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
IdentityRole role = roleManager.FindByName(model.Id);
if (role != null)
{
role.Name= model.Name;
IdentityResult result = roleManager.Update(role);
if (result.Succeeded)
{
return RedirectToAction("Index");
}
else
{
ModelState.AddModelError("", "Something went wrong!");
}
}
return View(model);
}
I have 2 questions:
1.) I have placed the Fine Uploader in a form and now I'm wondering why I don't see the filled content of the entry fields in my controller. How I can solve that?
2.) How can I do field validations before the upload process fires?
I hope someone can help!
Here is my code:
Model:
public class UploadFileModel
{
[StringLength(100)]
[Display(Name = "* Title:")]
public string Title { get; set; }
[StringLength(300)]
[Display(Name = "Description:")]
public string Description { get; set; }
}
View:
#model mowee.Models.UploadFileModel
<link href="~/Scripts/fineuploader/fineuploader-3.5.0.css" rel="stylesheet" />
#using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { id = "uploadForm", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<fieldset>
<legend>Video Upload</legend>
<ol>
<li>
#Html.LabelFor(m => m.Title)
#Html.TextBoxFor(m => m.Title, new { #Class = "action add", title = "Enter your video/movie title here." })
</li>
<li>
#Html.LabelFor(m => m.Description)
#Html.TextAreaFor(m => m.Description, new Dictionary<string, object> { { "rows", "3" } })
</li>
</ol>
<div id="bootstrapped-fine-uploader"></div>
<script src="~/Scripts/fineuploader/fineuploader-3.5.0.js"></script>
<script>
function createUploader() {
var uploader = new qq.FineUploader({
element: document.getElementById('bootstrapped-fine-uploader'),
multiple: false,
validation: {
sizeLimit: 2147483648 //2GB
},
request: {
endpoint: '/Home/UploadFile'
},
text: {
uploadButton: '<div><i class="icon-upload icon-white"></i>* Upload Video</div>'
},
template: '<div class="qq-uploader span12">' +
'<pre class="qq-upload-drop-area span12"><span>{dragZoneText}</span></pre>' +
'<div id="btnUpload" class="qq-upload-button btn btn-success" style="width: 33%;">{uploadButtonText}</div>' +
'<span class="qq-drop-processing"><span>{dropProcessingText}</span><span class="qq-drop-processing-spinner"></span></span>' +
'<ul class="qq-upload-list" style="margin-top: 10px; text-align: center;"></ul>' +
'</div>',
classes: {
success: 'alert alert-success',
fail: 'alert alert-error',
dropActive: "cssClassToAddToDropZoneOnEnter"
}
});
}
window.onload = createUploader;
</script>
</fieldset>
}
Controller:
[HttpPost]
[AllowAnonymous]
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult UploadFile(string qqfile, UploadFileModel myModel)
{
if (ModelState.IsValid)
{
try
{
HttpPostedFileBase uploadFile = null;
uploadFile = Request.Files[0];
if (uploadFile != null && uploadFile.ContentLength > 0)
{
if (myModel.Title != null || myModel.Description != null)
{
**//but UploadFileModel is null. WHY??????? Anyone an idea what i did wrong???
//write data to DB**
}
}
else
{
ModelState.AddModelError("", "Please choose a video/movie.");
return Json(new { success = false, message = "Please choose a video/movie." }, "application/json");
}
}
catch (Exception ex)
{
ModelState.AddModelError("", "An error occured. Try again.");
mailUtils.SendBugMail(ex, this.HttpContext);
return Json(new { success = false, message = "An error occured during upload. Try again." }, "application/json");
}
return Json(new { success = true, VideoLink = #ViewBag.VideoLink, VideoTranscoded = #ViewBag.Transcoded }, "application/json");//"text/html");
}
return Json(new { success = false, message = "An error occured during upload. Try again." }, "application/json");
}
OK. I figured it out. The params can be set on callback 'onSubmit' with setParams like that:
callbacks: {
onSubmit: function (id, fileName, responseJSON) {
uploader.setParams({
idxTitle: $('#titleId').val(),
idxAuthor: $('#authorId').val(),
idxEmail: $('#emailId').val()
});
},
And it works fine!
Addressing your questions:
You should really have a look at the MVC4 example in the Fine Uploader server-side examples repository. Model your server-side code after this example, and you should be fine. I personally am not an MVC4 developer, but I know the example I have linked to works.
You can make use of onValidate and onValidateBatch callbacks to perform your own validation tasks. Please have a look at the callbacks documentation for more info.
I have a situation where I need to edit an enumerable property in a view model:
public class ViewModel
{
public MyObj Obj { get; set; }
public IEnumerable<MyObj> MyObjs = new List<MyObj>();
}
I have followed this post; controller action:
public ActionResult Index()
{
var viewModel = new ViewModel();
viewModel.Obj = new Obj() { Name = "0", Value = true };
var o1 = new MyObj() { Name = "1", Value = false };
var o2 = new MyObj() { Name = "2", Value = false };
viewModel.Objs = new List<Obj>() { o1, o2 };
return View(viewModel);
}
[HttpPost]
public ActionResult Index(ViewModel viewModel)
{
return View(viewModel);
}
The Index view as follows:
<% using (Html.BeginForm()) { %>
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<%= Html.EditorFor(x => x.Objs) %>
</table>
<br />
<input type="submit" value="Submit" />
<% } %>
And the editor template in "~/Views/Home/EditorTemplates/Obj.ascx":
<tr>
<td><%: Html.TextBoxFor(x => x.Name) %></td>
<td><%: Html.CheckBoxFor(x => x.Value) %></td>
</tr>
The issue is: browse to Index, the data shows up. The POST, and the enumerable data disappears. Stepping through, the singular "Obj" in the view model remains, so it is just the enumerable data that is disappearing.
I have been staring at this for some time now, if any one could help out it would be brilliant.
Cheers,
Tim.
Take a look at this post by Phil Haack, MVC2 doesn't natively support binding a list back to the viewmodel unless you do a little manipulation.
Update: I've looked into this a little more and think you should try adding TryUpdateModel(viewModel.MyObjs, "MyObjs"); to your Controller. This informs the modelbinder that it should use the "MyObjs" binding prefix to attach the data from the form to the collection in your ViewModel.
I have the following code in my view:
<% using (Ajax.BeginForm("JsonCreate", new AjaxOptions { OnComplete = "createCategoryComplete" }))
{ %><div id="createCategory">
<fieldset>
<legend>Add new category</legend>
<p>
<%=Html.TextBox("CategoryId")%>
<%=Html.TextBox("Test")%>
<label for="name">Name:</label>
<%= Html.TextBox("Name")%>
<%= Html.ValidationMessage("Name")%>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
</div>
In the controller the code is as follows:
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult JsonCreate(string Name)
{
if (ModelState.IsValid)
{
try
{
//Return a json object to the javascript
return Json(new { CategoryId = 123, Test= "test successful" });
}
catch
{
#region Log errors about the exception
//Log error to administrator here
#endregion
}
}
//If we got this far, something failed, return an empty json object
return Json(new { /* Empty object */ });
}
What should be the code in the view for the following function to read the values returned by the Json and update the textboxes for CategoryId and Test?
function createCategoryComplete() {....???}
function createCategoryComplete(e) {
var obj = e.get_object();
alert(obj.CategoryId + ' ' + obj.Test);
}
Try this,
success: function(data) {
alert(data.CategoryId + " " + data.Test);
EDIT:
function createCategoryComplete(data)
{
document.getElementById("UrTxtBoxID").value = data.Test;
}