CRUD Operations in ASP.NET MVC 4 - asp.net-mvc-4

I have to make a ASP.NET MVC 4 Page which contains Customer details.
One form I have to create in which I have to perform Customer Create, Update and Delete.
The different fields are..
1) Customer ID
2) Customer Name
3) Customer Image
4) Customer Address
Now, I am confused with Customer Image. How to store Image in database and how to display it in Gridview from database. Please solve my problem as it's very important for me..

As #LajosArpad said save image as file and only save path of the image in database.
Here is view for creating customer
<div class="box box-primary">
#using (Html.BeginForm("Create", "Customer", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal box-body">
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Address, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Address, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Address, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Image</label>
<div class="col-md-10">
<input class="form-control" name="image" type="file" />
</div>
</div>
</div>
<div class="box-footer">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
}
</div>
And controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Exclude = "Id")] Customer customer, HttpPostedFileBase image)
{
if (ModelState.IsValid)
{
if (image != null && image.ContentLength > 0)
{
var filePath = GetFilePath(image.FileName);
image.SaveAs(filePath);
customer.ImageUrl = "~/images/upload/" + Path.GetFileName(filePath);
}
// Save customer to database
return RedirectToAction("Index");
}
return View(news);
}
// Get absolute path for saving image and check it does not exist
public static string GetFilePath(string fileName)
{
var targetFolder = System.Web.Hosting.HostingEnvironment.MapPath("~/images/upload/");
var targetPath = Path.Combine(targetFolder, fileName);
if (File.Exists(targetPath))
{
var name = Path.GetFileNameWithoutExtension(fileName);
name = name + "-" + (new Random()).Next();
var extension = Path.GetExtension(fileName);
name = name + extension;
GetFilePath(name);
}
return targetPath;
}

You store the image as a file and you store the path of the image in the database. If I were you I would generate the filenames instead of using the original filenames to make sure they are not duplicated. So you do not need to store the images in the database, you can store them as separate files.

Related

The submit button doesn't go to the post method in the contoller

The submit button doesn't go to the post method in the controller. Help please, I am new to programming in ASP.Net and I am trying to debug why the submit button doesn't go the the post method in the controller.
We also are trying to use web services
Here is the code for the Account/View/Login.cshtml
#using WebApplication3.Models
#model LoginViewModel
#{
ViewBag.Title = "Log in";
}
<h2>#ViewBag.Title.</h2>
<div class="row">
<div class="col-md-8">
<section id="loginForm">
#using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Use a local account to log in.</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
#Html.CheckBoxFor(m => m.RememberMe)
#Html.LabelFor(m => m.RememberMe)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Log in" class="btn btn-default" />
</div>
</div>
<p>
#Html.ActionLink("Register as a new user", "Register")
</p>
#* Enable this once you have account confirmation enabled for password reset functionality
<p>
#Html.ActionLink("Forgot your password?", "ForgotPassword")
</p>*#
}
</section>
</div>
<div class="col-md-4">
<section id="socialLoginForm">
#Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl })
</section>
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Here is the partial code for the controller
// GET: /Account/Login
[AllowAnonymous]
public ActionResult Login()
{
return View();
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var RenewalClient = this.RenewalClient.ServiceClient;
bool isValidUser= RenewalClient.ValidateUser(model.Email,model.Password);
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
Your html seems to be fine. It is always good to pass any information using anonymous function as last argument in BeginForm("Login","Account",FormMethod.Post, new {}).
Check whether your controller action is decorated with [HttpPost] attribute because if this attribute is not present on the action method, it will serve only GET request.

Submit button is submitting but not saving - MVC

I have tried many things to get the submit button to submit to the database. I'm not getting any errors, and the two error messages for testing, one from the controller, one from the view, are not printing to let me know that it is not working. Upon user hitting submit, it renders and displays the same button- Set Statement, instead of the new text that the user entered. Not sure how to fix or where the problem is.
Here is the code:
Controller:
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Create(TableA Statement)
{
var model = new Test.Models.Tables();
using (var db = new Entities())
if (ModelState.IsValid)
{
TableA tablea = new TableA();
tablea.Statement = model.Statement;
db.TablesA.Add(tablea);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
return Content("Failed");
}
}
Main View:
<td>
#if (tablea.Statement != null)
{
#Html.DisplayFor(modelItem => tablea.Statement)
<text>|</text>
#Html.ActionLink("Edit", "Edit", new { id = tablea.ID })
}
else
{
Html.RenderAction("PopUp");
var model = new Test.Models.Tables();
if (model.Statement != null) {
<text>Save Successful!</text>
}
}
</td>
Popup View:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
=
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Statement, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Statement)
#Html.ValidationMessageFor(model => model.Statement)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" onsubmit="Create(Statement)" class="btn btn-default">
</div.. etc>
Popup View is a partial view or what?, I recommend convert it to partial view, and in your controller you can do something like
public ActionResult CreatePartial()
{
var pages = pageRepository.Pages;
return PartialView(pages);
}
and in your view use
#{Html.RenderAction("Popup", "CreatePartial");}
if your model of partial is different of model of main view, if not use:
#Html.RenderPartial("ViewName")

Register Page View doesnot work in Main Page View

First of all i have a register page like this
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<form role="form" action="" method="post" class="login-form">
<div class="form-group">
<div>
#Html.TextBoxFor(model => model.Name, new { #class = "form-username form-control", placeholder = "Name" })
</div>
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.UserName, new { #class = "form-username form-control", placeholder = "User Name" })
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.Email, new { #class = "form-username form-control", placeholder = "Email" })
</div>
<div class="form-group">
#Html.PasswordFor(model => model.Password, new { #class = "form-username form-control", placeholder = "Password" })
</div>
<input type="submit" value="Register" class="btn" />
</form>
}
and when i try register with that page,i register and add account to database.But i want to use this register page render at Main page and use like that but when i do that it doesn't work.
<div class="form-bottom">
#RenderPage("~/Views/User/Register.cshtml")
</div>
and this is the controller code.
public ActionResult Register()
{
return View(new RegisterModel());
}
[HttpPost]
public async Task<ActionResult> Register(RegisterModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var siteContext = new SiteContext();
var user = new User
{
Name = model.Name,
Email = model.Email,
Password=model.Password,
UserName=model.UserName
};
await siteContext.Users.InsertOneAsync(user);
return RedirectToAction("Profile", "MainPage");
}
To be honest the whole view is a bit of a mess when you use Html.BeginForm() you don't need another form inside that. Your view should look like:
#using (Html.BeginForm("{Action}", "{Controller}", FormMethod.Post, new { #class = "login-form"}))
{
#Html.AntiForgeryToken()
<div class="form-group">
<div>
#Html.TextBoxFor(model => model.Name, new { #class = "form-username form-control", placeholder = "Name" })
</div>
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.UserName, new { #class = "form-username form-control", placeholder = "User Name" })
</div>
<div class="form-group">
#Html.TextBoxFor(model => model.Email, new { #class = "form-username form-control", placeholder = "Email" })
</div>
<div class="form-group">
#Html.PasswordFor(model => model.Password, new { #class = "form-username form-control", placeholder = "Password" })
</div>
<input type="submit" value="Register" class="btn" />
}
You need to replace {Action} with the name of the action, Register. Also replace {Controller} with the name of the controller.
Some useful documentation.

How to get the Minimum/Maximum value from the Range attribute

The View I have added looks as below and I have used the Range Attribute for Model.
#Model System.ComponentModel.DataAnnotations.RangeAttribute
#{Layout = null;}
#Html.Hidden("IncludedValidators", "RangeAttribute")
<div class="page-header">
<h4>
MinMaxRangeValidator
</h4>
<div>
<span class="icon-remove pull-right"></span>
</div>
</div>
<div class="control-group">
#Html.LabelFor(p => p.Minimum, new { #class = "control-label" })
<div class="controls">
#Html.TextBoxFor(p => p.Minimum, new { #class = "input-medium" })
</div>
</div>
<div class="control-group">
#Html.LabelFor(p => p.Maximum, new { #class = "control-label" })
<div class="controls">
#Html.TextBoxFor(p => p.Maximum, new { #class = "input-medium" })
</div>
</div>
<div class="control-group">
#Html.LabelFor(p => p.ErrorMessage, new { #class = "control-label" })
<div class="controls">
#Html.TextBoxFor(p => p.ErrorMessage, new { #class = "input-medium" })
</div>
</div>
And My controller Looks like:
public ActionResult AddValidator(string validatorType)
{
ValidationAttribute validator = null;
switch (validatorType)
{
case "RequiredAttribute":
validator = new RequiredAttribute();
break;
case "RangeAttribute":
validator = new RangeAttribute(minimum,maximum);
break;
}
}
How do I get the minimum and maximum values here? I have not created a separate method under the controller for each type of validation.
Your inputs need to be wrapped in a form like:
#using (Html.BeginForm())
{
...
}
and your controller action should be receiving the View Model as a parameter:
public ActionResult AddValidator(RangeAttribute rangeAttribute)
{
rangeAttribute.Maximum;
rangeAttribute.Minimum;
}

How to upload Photos/ Images in Asp.Net 4.o Project

I want to add upload photo features in my MVC 4.0 Project, Please can you tell me how can I do that. I am using MVC 4.o and for Photo option i want to give file / image upload. Here is my Code
#model WebCart.Category
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("Create", "Category", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Category</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Photo)
</div>
<div class="editor-field">
<input name="PhotoFile" id="File" type="file"/>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
[HttpPost]
[ValidateInput(false)]
public ActionResult Create(Category category)
{
if (ModelState.IsValid)
{
db.Categories.AddObject(category);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(category);
}
Your controller action could take an additional PhotoFile argument:
[HttpPost]
[ValidateInput(false)]
public ActionResult Create(Category category, HttpPostedFileBase photoFile)
{
if (ModelState.IsValid)
{
// you could manipulate the PhotoFile parameter here
// for example let's store the uploaded file to a folder on the server
if (photoFile != null && photoFile.ContentLength > 0)
{
var fileName = Path.GetFileName(photoFile.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
photoFile.SaveAs(path);
}
db.Categories.AddObject(category);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(category);
}
Or if you want to read the uploaded file as a byte array you could use the following:
byte[] photo = new byte[photoFile.InputStream.Length];
photoFile.InputStream.Read(photo, 0, photo.Length);
// Now you could assign the byte array to some property of your model
// and persist it into the database (even if this is a bad practice -
// it would be more correct to store the photo on the file system and
// only store the full path to the photo in the database)
A must read article for uploading files in ASP.NET MVC is the following: http://haacked.com/archive/2010/07/16/uploading-files-with-aspnetmvc.aspx