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.
Related
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);
}
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.");
}
How can i make an image as an Ajax Action Link?
You could do this:
<a href="<%: Url.Action("someaction", "somecontroller") %>" id="mylink">
<img src="<%: Url.Content("~/images/foo.png") %>" alt="foo" />
</a>
and then in a separate javascript file AJAXify this link:
$(function() {
$('#mylink').click(function() {
$.ajax({
url: this.href,
type: 'GET',
success: function(result) {
alert('success');
}
});
return false;
});
});
And if you want to avoid the tag soup in your views you could write a custom helper:
public static class HtmlExtensions
{
public static MvcHtmlString ImageLink(this HtmlHelper htmlHelper, string actionName, string controllerName, object routeValues, object htmlAttributes, string imageSource)
{
var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection);
var image = new TagBuilder("img");
image.Attributes["src"] = urlHelper.Content(imageSource);
var anchor = new TagBuilder("a");
anchor.Attributes["href"] = urlHelper.Action(actionName, controllerName, routeValues);
anchor.MergeAttributes(new RouteValueDictionary(htmlAttributes));
anchor.InnerHtml = image.ToString(TagRenderMode.SelfClosing);
return MvcHtmlString.Create(anchor.ToString());
}
}
and then in your view simply:
<%: Html.ImageLink(
"someaction",
"somecontroller",
null,
new { id = "mylink" },
"~/images/foo.png"
) %>
and of course the process of AJAXifying it stays the same.
What about something like:
<a href='<%= Url.Action(...) %>'><img src='...' /></a>
Not certain if there is a helper that does this.
Bob
To push the id to the edit control whilst displaying an edit image instead of the word Spag you can try this:
#MvcHtmlString.Create(
Ajax.ActionLink("Spag", "Edit",
new { id = item.x0101EmployeeID },
new AjaxOptions() {
UpdateTargetId = "selectDiv",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET"
}
).ToHtmlString().Replace(
"Spag",
"<img src=\"" + Url.Content("../../Images/edit.png") + "\" />"
)
)
I have asp.net mvc application in c# language. I want to develop the scenario like, my page will have have the 4 dropdown controls. on the selection of first , second's item should be load, on selction of 2'nd, 3'rd dropdown should be load it item. where as 4'th is independent. but on 4'th dropdown I want to change the UI design. what strategy I have to use here? how can i implement this scenario here.?
Edited:
Controller->action
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetSubjects(int standardId)
{
List<Subject> subjectList = basicEntityManager.GetSubjects(standardId);
JsonResult result=Json(subjectList, JsonRequestBehavior.AllowGet);
return result;
}
i am able to debug this but not fetching data.
Script:
<script type="text/javascript">
$(function() {
$('#StandardId').change
(function() {
var url='/Test/GetSubjects';
fetchItems(url, { standardId: $(this).val() }, $('#SubjectId')
);
/* $('#SubjectId').change(function() {
fetchItems(
'/Test/GetChapters',
{
selectedItem1: $('#SubjectId').val(),
selectedItem2: $(this).val()
},
$('#SelectedItem3')
);
});*/
});
});
function fetchItems(url, data, ddl) {
$.getJSON(url, data, function(items) {
alert(items);
$.each(items, function() {
ddl.append
(
$('<option/>').val(this.Value).text(this.Text)
);
});
});
}
function OnStandardChange() {
var standard = document.getElementById("StandardId");
var subject = document.getElementById("SubjectId");
var ActionUrl = "/Test/GetSubjects/"
alert("Hi");
// $.getJSON('/Test/GetSubjects', { standardId: standard.val() }, function(data) { });
}
$('#StandardId').change(function() {
});
function OnSubjectChange() {
}
function OnChapterChange() {
}
function addOption(selectbox, text, value) {
var optn = document.createElement("OPTION");
optn.text = text;
optn.value = value;
selectbox.options.add(optn);
}
</script>
You could cascade with AJAX:
Model:
public class MyViewModel
{
public string SelectedItem1 { get; set; }
public IEnumerable<SelectListItem> Items1 { get; set; }
public string SelectedItem2 { get; set; }
public string SelectedItem3 { get; set; }
public string SelectedItem4 { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
// Load initial data
Items1 = Enumerable.Range(1, 5).Select(x => new SelectListItem
{
Value = x.ToString(),
Text = "item " + x
})
};
return View(model);
}
public ActionResult Items2(string selectedItem1)
{
// invoked to populate the second DDL
return Json(
Enumerable.Range(1, 3).Select(x => new { Value = x, Text = x }),
JsonRequestBehavior.AllowGet
);
}
public ActionResult Items3(string selectedItem1, string selectedItem2)
{
// invoked to populate the third DDL
return Json(
Enumerable.Range(1, 3).Select(x => new { Value = x, Text = x }),
JsonRequestBehavior.AllowGet
);
}
public ActionResult Items4(string selectedItem1, string selectedItem2, string selectedItem3)
{
// invoked to populate the fourth DDL
return Json(
Enumerable.Range(1, 3).Select(x => new { Value = x, Text = x }),
JsonRequestBehavior.AllowGet
);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
View:
<script type="text/javascript">
$(function () {
$('#SelectedItem1').change(function () {
fetchItems(
'<%= Url.Action("items2") %>',
{
selectedItem1: $(this).val()
},
$('#SelectedItem2')
);
});
$('#SelectedItem2').change(function () {
fetchItems(
'<%= Url.Action("items3") %>',
{
selectedItem1: $('#SelectedItem1').val(),
selectedItem2: $(this).val()
},
$('#SelectedItem3')
);
});
$('#SelectedItem3').change(function () {
fetchItems(
'<%= Url.Action("items4") %>',
{
selectedItem1: $('#SelectedItem1').val(),
selectedItem2: $('#SelectedItem2').val(),
selectedItem3: $(this).val()
},
$('#SelectedItem4')
);
});
$('#SelectedItem4').change(function () {
alert('changing UI');
});
});
function fetchItems(url, data, ddl) {
$.getJSON(url, data, function (items) {
$.each(items, function () {
ddl.append(
$('<option/>').val(this.Value).text(this.Text)
);
});
});
}
</script>
<% using (Html.BeginForm()) { %>
<%= Html.DropDownListFor(x => x.SelectedItem1, new SelectList(Model.Items1, "Value", "Text"))
<%= Html.DropDownListFor(x => x.SelectedItem2, Enumerable.Empty<SelectListItem>()) %>
<%= Html.DropDownListFor(x => x.SelectedItem3, Enumerable.Empty<SelectListItem>()) %>
<%= Html.DropDownListFor(x => x.SelectedItem4, Enumerable.Empty<SelectListItem>()) %>
<input type="submit" value="OK" />
<% } %>
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;
}