Pass modelstate errors of Image upload to a view - asp.net

I need validation for Image uploading. I have written validations using modelstate in my controller and I need to pass those validations in my view.
my view is
<div id="MemberPicture">
#using (Html.BeginForm("UpdateMemberPhotoDetails", "Member",FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<b> Pictures </b>
<table>
<tr>
<td>
<img src= "#Url.Content(Model.ImagePath)" alt="Image" width="200" height="200"/>
</td>
</tr>
<tr>
<td>
<input type="file" style="width:500px;" name="imgfile" id="file" data-val="true" data-val-required="File is required" />
</td>
</tr>
<tr>
<td><input type="submit" value="Upload" class="ButtonStyleForProfiles"/></td></tr>
</table>
}
</div>
and my control code is
public ActionResult UpdateMemberPhotoDetails( HttpPostedFileBase imgfile)
{
if (ModelState.IsValid)
{
if (imgfile == null)
{
ModelState.AddModelError("File", "Please Upload Your imgfile");
}
else if (imgfile.ContentLength > 0)
{
int MaxContentLength = 1024 * 1024; //1 MB
string[] AllowedFileExtensions = new string[] { ".jpg", ".png" };
var fileExtension = imgfile.FileName.Substring(imgfile.FileName.LastIndexOf('.'));
if (!AllowedFileExtensions.Contains(fileExtension))
{
ModelState.AddModelError("File", "Please imgfile of type: " + string.Join(", ", AllowedFileExtensions));
}
else if (imgfile.ContentLength > MaxContentLength)
{
ModelState.AddModelError("File", "Your imgfile is too large, maximum allowed size is: " + MaxContentLength + " MB");
}
else
{
var folderName = UserDetailsUtil.GetMemberPhotoPathFolderName(SessionData.UserID);
var fileName = SessionData.UserID;
var path = Path.Combine(Server.MapPath("~/Content/Upload/MemberProfilePhotos/" + folderName), fileName + fileExtension);
imgfile.SaveAs(path);
ModelState.Clear();
ViewBag.Message = "Image uploaded successfully";
}
}
}
return View();
}
How can I return modelstate errors to my view. and the viewbag message should print once the image is saved. can someone help me

after
#using (Html.BeginForm())
{
write this line:
#Html.ValidationSummary(true)
or you can do an if statement to show an error message:
#if (!ViewData.ModelState.IsValid)
{
//show error
}

Related

ASP.NET CORE 5 MVC How Can I Implement A Working Search Bar?

I have created a project site to which you can upload, download, delete and preview files. I want to have a search bar implemented, but being new to C# I have no idea how to link it or implement it correctly in the controller. Can anyone help me out? Thank you so much! (keep in mind I do not have a database)
<form methord="post" enctype="multipart/form-data" asp-controller="Home" asp-action="Index">
<input type="file" name="fifile" />
<input type="submit" value="Upload" />
<hr />
</form>
<table class="table">
<tr>
<th>File Name</th>
</tr>
#foreach (var item in FileClass.Filename)
{
<tr>
<td>#item.Name</td>
<td>Download</td>
#if (User.IsInRole("Admin"))
{
<td>Delete</td>
}
<td>Viewer</td>
</tr>
}
</table>
this is the razor view page, and I will also leave my controller code for the file manipulation:
FileClass fc = new FileClass();
[HttpPost]
public async Task<IActionResult> Index(IFormFile fifile)
{
string ext = Path.GetExtension(fifile.FileName);
var fisave = Path.Combine(_iweb.WebRootPath, "Uploads", fifile.FileName);
var stream = new FileStream(fisave, FileMode.Create);
await fifile.CopyToAsync(stream);
stream.Close();
return RedirectToAction("Index");
}
public IActionResult Index()
{
var displayfc = Path.Combine(_iweb.WebRootPath, "Uploads");
DirectoryInfo di = new DirectoryInfo(displayfc);
List<FileInfo> fileinfo = di.GetFiles().ToList(); ;
FileClass.Filename = fileinfo;
return View();
}
public IActionResult Delete(string filedel)
{
filedel = Path.Combine(_iweb.WebRootPath, "Uploads", filedel);
FileInfo fi = new FileInfo(filedel);
if (fi != null)
{
System.IO.File.Delete(filedel);
fi.Delete();
}
return RedirectToAction("Index");
}
public async Task<IActionResult> Download(string filename)
{
if (filename == null)
return Content("filename is not avaiable");
var path = Path.Combine(_iweb.WebRootPath, "Uploads", filename);
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, GetContentType(path), Path.GetFileName(path));
}
private string GetContentType(string path)
{
var types = GetMimeTypes();
var ext = Path.GetExtension(path).ToLowerInvariant();
return types[ext];
}
private Dictionary<string, string> GetMimeTypes()
{
return new Dictionary<string, string>
{
{".txt", "text/plain"},
{".pdf", "application/pdf"},
{".doc", "application/vnd.ms-word"},
{".docx", "application/vnd.ms-word"},
{".xls", "application/vnd.ms-excel"},
{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
{".png", "image/png"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".gif", "image/gif"},
{".csv", "text/csv"}
};
}
I do not know how to properly route , a sample code would be greatly appreciated, God Bless!
If you want to add search bar to the table,you only need to use js to filter the table data,here is a demo:
<form methord="post" enctype="multipart/form-data" asp-controller="Home" asp-action="Index">
<input type="file" name="fifile" />
<input type="submit" value="Upload" />
<hr />
</form>
<div>
File Name:<input id="search" />
<button onclick="search()">search</button>
</div>
<table class="table">
<tr>
<th>File Name</th>
</tr>
#foreach (var item in FileClass.Filename)
{
<tr>
<td>#item.Name</td>
<td>Download</td>
#if (User.IsInRole("Admin"))
{
<td>Delete</td>
}
<td>Viewer</td>
</tr>
}
</table>
#section scripts
{
<script>
function search() {
$("tr").each(function (index, value) {
if (index > 0 && !$(this).find("td")[0].innerText.includes($("#search").val())) {
$(this).attr("hidden", true);
} else {
$(this).removeAttr("hidden");
}
console.log(value);
})
}
</script>
}
result:

Why role.Name can get data?

I built "Role edit page" but role.Name can't get role data and It Happens NulReference eror. There is Two role in data but role.Name isn`t get them I research about that But I can't fixed this problem
what do you think about that?
Please Help me I Don't know what am I doing
Controller
public async Task<IActionResult> RoleEdit(string id)
{
var role = await _roleManager.FindByIdAsync(id);
var members = new List<User>();
var nonMembers = new List<User>();
foreach (var user in _userManager.Users.ToList())
{
var list = await _userManager.IsInRoleAsync(user, role.Name) ?
members : nonMembers;
list.Add(user);
}
var model = new RoleDetails()
{
Role = role,
Members = members,
NonMembers = nonMembers
};
return View();
}
RoleEdit View
#model RoleDetails
<div class="row">
<div class="col-md-12">
<form asp-controller="Admin" asp-action="RoleEdit">
<h6 class="bg-info text-white p-1"> Add To #Model.Role.Name</h6>
<table>
#if (Model.NonMembers.Count() == 0)
{
<tr>
<td>
Bütün istfadəçilər rola aid
</td>
</tr>
}
else
{
foreach (var user in Model.NonMembers)
{
<tr>
<td>
#user.UserName
</td>
<td>
<input type="checkbox" name="IdsToAdd" value="#user.Id" />
</td>
</tr>
}
}
</table>
<hr />
</form>
</div>
</div>
Try this:
public ActionResult Edit(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
RoleDetails roleDetails = db.RoleDetails.Find(id);
if (RoleDetails == null)
{
return HttpNotFound();
}
return View(RoleDetails);
}
I don't know what your database name is but you can change it.
If your goal is to have a crud system try this

Allow user to see only their uploaded data (Asp.NET MVC5)

I can upload and download the uploaded files, but I want that users to be able to see only their files. (user1 to see only his data, not also user2's data) How could I do it? Any idea could help. Thanks!
This is my controller, I know that between admin, user, editor I can restrict the access with Authorize, but this wouldn't help me restricting the access between user_id's.
(need to mention that privacy is a very important aspect of my project)
public class FileUploadController : Controller
{
// GET: FileUpload
public ActionResult Index()
{
var items = GetFiles();
return View(items);
}
// POST: FileUpload
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
if(file != null && file.ContentLength > 0 )
try
{
string path = Path.Combine(Server.MapPath("~/Files"),
Path.GetFileName(file.FileName));
file.SaveAs(path);
ViewBag.Message = "File uploaded successfully";
}
catch(Exception ex)
{
ViewBag.Message = "ERROR:" + ex.Message.ToString();
}
else
{
ViewBag.Message = "You have not specified a file.";
}
var items = GetFiles();
return View(items);
}
public FileResult Download(string downloadedfile)
{
var FileVirtualPath = "~/Files/" + downloadedfile;
return File(FileVirtualPath, "application/force-download", Path.GetFileName(FileVirtualPath));
}
private List <string> GetFiles()
{
var dir = new System.IO.DirectoryInfo(Server.MapPath("~/Files"));
System.IO.FileInfo[] fileNames = dir.GetFiles("*.*");
List<string> items = new List<string>();
foreach (var file in fileNames)
{
items.Add(file.Name);
}
return items;
}
}
This is the view:
<h2> File Upload </h2>
#model List<string>
#using (Html.BeginForm("Index", "FileUpload", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<label for="file"> Upload </label>
<input type="file" name="file" id="file" />
<br /><br />
<input type="submit" value="Upload" />
<br /><br />
#ViewBag.Message
<br/>
<h2>Documents list</h2>
<table style="width:100%">
<tr>
<th> File Name </th>
<th> Link </th>
</tr>
#for (var i = 0; i <= (Model.Count)-1 ; i++)
{
<tr>
<td>#Model[i].ToString() </td>
<td>#Html.ActionLink("Download", "Download", new { downloadedfile = Model[i].ToString() }) </td>
</tr>
}
</table>
}
<style>
table, th, td {
border: 1px solid white;
}
</style>
You can separate to folder, create a folder with the id of the user, and put the data in user folder.
When you gonna list, only show the folder of the user

Renderpartial in a foreach loop only sends the first element in list

I'm trying to send a User in a list of users to a partial view but the partial view only takes the first user in the list. The code correctly displays the username and the actionlink to profile but for some reason only the first user in the list is sent to the partial view in every iteration.
What I want to do is to dynamically show the "confirmDelete" partial view when the delete button is clicked and delete the correct user.
Help is appreciated!
Edit:
I think I see the problem now, I name the url pointing to the Delete-Action "RedirectTo" in every partial view, and also all the divisions have the same id.. Still don't know how to fix it though.
MainView:
#foreach (var item in ViewBag.UsersList as List<CommonLibrary.User>)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.ActionLink("Profile", "ProfilePage", new { id = item.UserId }) |
#{
var user = Homepage.Service.SessionHelper.GetSessionUser(Context);
if (user != null && user.GetType().ToString() == "CommonLibrary.Operator" && item.UserId != user.UserId)
{
<button id="#item.UserId" class="btn-danger" onclick="confirmDelete()">Delete</button>
<div style="width:40%; float:right;">
#{
await Html.RenderPartialAsync("_ConfirmDelete", item);
}
</div>
}
}
</td>
</tr>
}
Partial View:
#model CommonLibrary.User
#Html.Hidden("RedirectTo", Url.Action("Delete", "Users", new { id = Model.UserId }))
<div style="display:none" id="confDelete">
<div>
<b>Are you sure you want to delete user: #Model.UserName?</b>
</div>
<button id="Yes" class="btn-danger" onclick="deleteConfirmed()">Yes</button>
<button id="No" class="btn-secondary" onclick="hideDelete()">No</button>
</div>
<script>
function confirmDelete() {
$("#confDelete").show();
$("#del_btn").hide();
}
function hideDelete() {
$("#confDelete").hide();
$("#del_btn").show();
}
function deleteConfirmed() {
var url = $("#RedirectTo").val();
location.href = url;
}
</script>
I figured it out by using UserId as id for the different elements.
Main View:
<tbody>
#foreach (var item in ViewBag.UsersList as List<CommonLibrary.User>)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.ActionLink("Profile", "ProfilePage", new { id = item.UserId }) |
#{
var user = Homepage.Service.SessionHelper.GetSessionUser(Context);
if (user != null && user.GetType().ToString() == "CommonLibrary.Operator" && item.UserId != user.UserId)
{
<button id="#item.UserId" class="btn btn-danger" onclick="confirmDelete(this.id)">Delete</button>
<div style="width:40%; float:right;">
#{
await Html.RenderPartialAsync("_ConfirmDelete", item);
}
</div>
}
}
</td>
</tr>
}
</tbody>
</table>
<script>
function confirmDelete(id) {
var element = document.getElementById("div" + id);
element.style.display = "block";
}
function hideDelete(id) {
var element = document.getElementById("div" + id);
element.style.display = "none";
}
function deleteConfirmed(id) {
var url = "/Users/Delete/" + id;
window.location.href = url;
}
</script>
Partial View:
#model CommonLibrary.User
#{
var divId = "div" + Model.UserId.ToString();
}
<div style="display:none" id="#divId">
<div>
<b>Are you sure you want to delete user: #Model.UserName?</b>
</div>
<button id="#Model.UserId.ToString()" class="btn btn-danger" onclick="deleteConfirmed(this.id)">Yes</button>
<button id="#Model.UserId.ToString()" class="btn btn-secondary" onclick="hideDelete(this.id)">No</button>
</div>

How to retrieve form data and assign it to a text as a url on MVC 4

i would like to return below url from a search submit where id will be get from database.
So when a user search something by id it will search my database and display the result on my home view. then i want to transform my ID a clickable url which is this one:
http://myadress.com:8787/Handlers/DataExport.ashx?format=pdf&id=???&direction=0
Any idea how to do?
This is my home view:
<body>
<p>
#using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
<b>SEARCH BY:</b> #Html.RadioButton("searchby", "ID", true) <text>ID</text>
#Html.RadioButton("searchby", "NAME") <text>NAME</text>
<br /><br />
#Html.TextBox("search") <input type="submit" value="SEARCH" />
}
</p>
<table>
<tr>
<th>
ID
</th>
<th>
NAME
</th>
<th>Actions</th>
</tr>
#if (Model.Count() == 0)
{
<tr>
<td colspan="2">NO DATA FOUND.</td>
</tr>
}
else
{
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.NAME)
</td>
<td>
#Html.ActionLink("Details", "Details", new { id = item.id })
</td>
</tr>
}
}
this is my controller:
public class HomeController : Controller
{
private mydbEntities db = new mydbEntities();
//
// GET: /Home/
public ActionResult Index(string searchBy, string search)
{
if (searchBy == "ID")
{
return View(db.mytable.Where(x => x.ID == search).ToList());
}
else (searchBy == "NAME")
{
return View(db.mytable.Where(x => x.NAME == search).ToList());
}
}
You could just create an anchor tag and substitute the id in the href attribute
your link text
you have to use jquery for this. something like
$('.btnSearch').on('click', function(){
$('.lnkSubmit').attr('href', '#Url.Action("Action", "Controller", new { id = "----" })'.replace("----", (returned id here));
});
this will replace the url of a link with class lnkSubmit and will include the id that you put in it. Let me know if you have any questions.
In my Blog application, this is how I implemented search functionality for searching posts.
Partial view for search:
#using (Html.BeginForm("Search", "Blog", FormMethod.Get, new {id = "search-form"}))
{
<input type="text" name="s" placeholder="Search">
<button type="submit">Go</button>
}
Search action in controller:
public ActionResult Search(string s)
{
var model = _dbPostRepository.GetPostsForSearch(s);
ViewBag.TotalPosts = _dbPostRepository.TotalSearchPosts(s);
return View("Posts");
}
Posts View:
#model FirstBlog.Core.Post
#if (#ViewBag.TotalPosts > 0)
{
foreach (var item in Model)
{
Html.RenderPartial("_PostTemplate", item);
}
}
else
{
<p>No posts found!</p>
}
_PostTemplate is the view for each post. Hope this would help.

Resources