i am creating an asp.net mvc 5 web app(with angularjs)
in my app i am calling a controller to download user pic but the whole page is being refreshed,
and i don't want to postback the particular page
this is how my controller looks
[HttpPost]
public ActionResult profilecompletion(FormCollection fc, HttpPostedFileBase file)
{
// tbl_details tbl = new tbl_details();
var allowedExtensions = new[] {
".Jpg", ".png", ".jpg", "jpeg",".doc",".docx",".pdf",".xlsx",".xls"
};
string id = fc["name"].ToString();
//tbl.Id = fc["Id"].ToString();
//tbl.Image_url = file.ToString(); //getting complete url
//tbl.Name = fc["Name"].ToString();
if (file==null)
{
}
else
{
var fileName = Path.GetFileName(file.FileName); //getting only file name(ex-ganesh.jpg)
var ext = Path.GetExtension(file.FileName); //getting the extension(ex-.jpg)
if (allowedExtensions.Contains(ext)) //check what type of extension
{
string name = Path.GetFileName(id + fileName); //getting file name without extension
//string myfile = name + "_" + "" + ext; //appending the name with id
// store the file inside ~/project folder(Img)
if (!Directory.Exists(Server.MapPath("~/userpic")))
{
Directory.CreateDirectory(Server.MapPath("~/userpic"));
}
var path = Path.Combine(Server.MapPath("~/userpic"), name);
//tbl.Image_url = path;
//obj.tbl_details.Add(tbl);
//obj.SaveChanges();
file.SaveAs(path);
}
else
{
ViewBag.message = "Please choose only Image file";
}
}
return RedirectToAction("Dashboard", "Dashboard");
}
and this is my cshtml page
#using (Html.BeginForm("profilecompletion", "user", FormMethod.Post, new
{
enctype = "multipart/form-data"
}))
{
<div class="row">
<div class="col-sm-8">
<span>Profile Pic</span>
<input id="imagepath" type="file" file-model="profileimage" ng-text-change="changeimage()" name="file" />
</div>
<div class="col-sm-4">
<img id="myImg" src="#" alt="Choose image" style="height:100px; width:100px; border-radius:10px;" ng-hide="hidestat" ng-src="{{image}}" />
#*<input id="imagepath" type="file" file-model="profileimage" class="form-control" />*#
</div>
</div>
<div class="button-container">
<input type="submit" name="Update" class="btn btn-primary" ng-click="update()" title="save" />
</div>
}
the page load is preventing the app to execute update() function properly
what i need to do here to prevent any kind of postback or pageload without effecting any programmability.
The reason why the page reloads is because you are using a submit button which as its name suggests submits the form with a full postback to the server. You could use a regular button instead:
<input type="button" name="Update" class="btn btn-primary" ng-click="update()" title="save" />
Try this
<button type="button" name="Update" class="btn btn-primary" ng-click="update()" title="save" > Submit </button>
Related
I have a Form that should pass data through POST request, but GET request is being used without passing the data and do model binding of asp core, so buz of that the method Registrationp is never reach if the attribute [HttpPost] is in place ;( .
I tried many ways to get over this problem but none if them worked, even though the other forms post the data and bind the model successfully
HTML:
#model Student_Training.Models.File;
<form method="post" asp-controller="Students" asp-action="Registrationp" enctype="multipart/form-data">
<label asp-for="FileRep" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<div class="custom-file">
<input type="file" asp-for="FileRep" name="img" accept="image/*" class="form-control custom-file-input" />
<label class="custom-file-label"> Upload...</label>
</div>
</div>
<div class="form-group">
<button id="Button" type="submit" name="submit" formmethod="post" class="btn btn-secondary btn-sm">
<a asp-action="Registrationp"> Save </a>
</button>
</div>
</form>
Controller POST method:
[HttpPost]
public async Task<IActionResult> Registrationp([Bind("FileId, FileName, OwnerId, FileRep")] Student_Training.Models.File imgFileModel, IFormFile img, int? id)
{
var user = await _userManager.FindByNameAsync(User.Identity.Name);
var userEmail = user.Email;
Student Student = _context.Student.FirstOrDefaultAsync(x => x.Email == userEmail).Result;
// StudentId
id = Student.StudentId;
// Save img to wwwroot/img folder
string wwwRootPath = _hostEnvironment.WebRootPath;
Student_Training.Models.File myFile = new Student_Training.Models.File();
string fileName = Path.GetFileNameWithoutExtension(imgFileModel.FileRep.FileName);
string extention = Path.GetExtension(imgFileModel.FileRep.FileName);
imgFileModel.FileName = fileName = fileName + DateTime.Now.ToString("yymmss") + extention;
string path = Path.Combine(wwwRootPath + "/img/", fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
await imgFileModel.FileRep.CopyToAsync(fileStream);
}
// insert recorod to Db
_context.Add(imgFileModel);
await _context.SaveChangesAsync();
return View();
}
As a matter of fact you are using an ancor tag to submit your form, not a submit button. An ancor tag is always generates a GET request. So just remove it from your code:
<button id="submitButton" type="submit" class="btn btn-secondary btn-sm">Save</button>
I have an API that I've created for user registration / authentication, and similar operations. Example post method:
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody]AuthenticateModel model)
{
var user = _userService.Authenticate(model.Username, model.Password);
if (user == null)
return BadRequest(new { message = "Username or password is incorrect" });
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.Id.ToString()),
new Claim(ClaimTypes.Role, user.Role)
}),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
// return basic user info and authentication token
return Ok(new
{
user.Id,
user.Username,
Token = tokenString,
});
I now need my front-end to implement my API. So I'd like to call this API from a View. For example, say I want to create a simple login page:
<div class="row">
<div class="col-md-12">
<form method="post" action="">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Username"></label>
<input asp-for="Username" class="form-control" />
<span asp-validation-for="Username" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
How would I now call the authenticate post method for this login form? As I have a controller which is the API controller, and I have a controller which is the action controller, for the users.
File structure if needed:
File structure
Calling your own web action can be done in mainly two ways:
Native HTML form submission.
AJAX
Native submit reloads your entire page. And address will be changed to the URL or your web action. Typically used as a search function, like:
<form asp-controller="Search" asp-action="Blogs" method="get">
<input type="text" name="question" />
<input type="submit" />
</form>
When the user submit the form with clicking the submit button, the browser will be redirect to /search/blogs?question=textHeInput.
To prevent page refreshing, you can submit a request with pure JavaScript. Which called AJAX.
https://en.wikipedia.org/wiki/Ajax_(programming)
For example:
// Require jQuery:
$.post('/authenticate', { "yourPropertyName" : "yourPropertyValue" }, function(response) {
// Do something after the request. Access response like this:
alert(response.Username);
});
And server responded username will shown.
You can use ASP.NET MVC Core Tag Helpers:
<form asp-controller="MyControllerName" asp-action="Authenticate" method="post">
<!-- Input and Submit elements -->
</form>
Since you're using JwtBearer with WebAPI's, an assumption is that you're probably going to call your authentication method using Ajax. Unfortunately you did not provide your class declaration showing your route convention for your ApiClass but normally it goes as "api/[Controller]"... If this is the case, you can do the following:
$("submitButton").click(
function authenticateUser()
{
$.post(
'/api/[COntrollerName]/authentication', // URL
$('#form").serialize(), // this is your form data as an object
function(payload) //Response
{
// do something with payload here
}
});
}
);
<button type="submit" class="btn btn-primary" id="submitButton">Login</button>
You might want to set your <button type="button"> so that the form doesn't submit. Attach a click event to that function, so that it processes the api call.
I have passed the UserID to the table as shown in the code:
View
#foreach (var user in Model.RIROUsers)
{
<tr>
<td class="text-center">#(user.FirstName + " " + user.LastName)</td>
<td>View Details</button>
</tr>
}
Modal
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-body">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="form-group col-md-4 col-md-offset-2">
<label for="">* Address</label>
<input type="text" class="form-control input-sm" value="">
<label for="">* Birthday</label>
<input type="text" class="form-control input-sm" value="">
<label for="">* Contact</label>
<input type="text" class="form-control input-sm" value="">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Controller
public ActionResult Index()
{
var vm = new RIROViewModel();
vm.RIROUsers = new List<ResourceViewModel>();
foreach (var user in db_RIRO.sp_GetAllRIRORoster())
{
vm.RIROUsers.Add(new ResourceViewModel()
{
EID = user.EID,
FirstName = user.FirstName,
LastName = user.LastName,
EmployeeType = user.EmployeeType,
ProjectName = user.ProjectName,
JobTitle = user.JobTitle,
Level = user.CareerLevel,
ACNRollOn = user.HireDate,
ManagerName = user.Manager,
LeadName = user.Supervisor,
UserID = user.UserID
});
}
return View(vm);
}
Now when I click View Details I want the details of the user to display on the modal. What would be the best approach on this? I'm thinking of creating another stored procedure to retrieve the User's details and display it on the modal. But how do I do this?
EDIT 1: Changed button to a href=~/Views/RIRO/id=#user.UserID
As Shyju said, use click DOM event to the anchor link to show modal popup. Here are the steps:
1) Put Url.Action with proper controller and action name into href attribute of anchor link, then assign a class name to help identify each link.
<a href="#Url.Action("Details", "User", new { id = user.UserID })"
class="btn btn-xs btn-primary details" data-toggle="modal"
data-target="#exampleModal" data-id="#user.UserID">View Details</a>
2) Handle click DOM event using JS which rather than opening a new window/tab in browser, it should open modal popup instead (by using jQuery.ajax(), jQuery.get() or jQuery.load()):
$('.details').click(function (ev) {
ev.preventDefault(); // this is required
// get target action
var action = $(this).attr('href');
$.get(action, function (data) {
$(this).find(".modal-body").html(data);
$('#exampleModal').modal('show');
});
});
// alternative way
$('.details').click(function (ev) {
ev.preventDefault(); // this is required
// get target action
var action = $(this).attr('href');
$('.modal-body').load(action, function () {
$('#exampleModal').modal('show');
});
});
3) Ensure that target action method returns partial view which will loaded to the modal popup.
public ActionResult Details(int id)
{
var vm = new RIROViewModel();
// do something to retrieve data from DB
return PartialView("_Details", vm);
}
References:
Implementing Bootstrap Modal Popup In MVC Application
How to get anchor text/href on click using jQuery?
I'm trying to learn more about MVC 5 so I'm writing a bloging site for myself to learn more as I go.
I have set up a select list for tags and would like to be able to add new tags from the create blog entry page rather than having to remember to set the tags up before creating a new post. I'm thinking down the lines of a "Add Tag" button which displays a bootstrap modal window where the user can add a new tag.
Here is my controller action:
public ViewResult CreateBlogPost()
{
CreateEditBlogViewModel viewModel = new CreateEditBlogViewModel();
viewModel.BlogPost = new Core.BlogPost();
viewModel.BlogPost.ShortBody = "<p>Something short and sweet to describe the post</p>";
viewModel.BlogPost.Body = "<p>Enter something blog worthy here...</p>";
viewModel.Tags = new SelectList(_blogRepo.BlogTags(), "Id", "Name");
viewModel.Categories = new SelectList(_blogRepo.BlogCategories(), "Id", "Name");
return View(viewModel);
}
And here is the HTML in the view:
<div class="row">
<div class="form-group">
#Html.LabelFor(m => m.BlogPost.Tags, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.ListBoxFor(m => m.SelectedTags, Model.Tags, new { #class = "form-control chosen-select", #data_placeholder = "Start typing to see a list of tags" })
</div>
</div>
</div>
<div class="row">
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#tagModal">
Add Tag
</button>
</div>
Here is my partial view for the modal window:
#using (Html.BeginForm("SaveTag", "Home", FormMethod.Post, new { id = "tag-form" }))
{
#Html.AntiForgeryToken()
<!-- Modal -->
<div class="modal fade" id="tagModal" tabindex="-1" role="dialog" aria-labelledby="tagModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="tagModalLabel">Enter a name for a new tag</h4>
</div>
<div class="modal-body">
<input type="text" id="Name" placeholder="Enter a new tag name" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
}
Is it possible to add a tag on the client side, persist it into the db and then add it to my tags select list without refreshing the page?
PS: FYI I'm using the Chosen multi-select from here.
#section scripts {
<script type="text/javascript" src="~/Scripts/chosen.jquery.min.js"></script>
<script type="text/javascript">
$(".chosen-select").chosen()
</script>
}
EDIT: I have updated the question with all the code that makes the view give the user the modal window to enter a new tag name. I'm just not sure how to post without navigating away from the page so I'm guessing some sort of Ajax post is required. And then what to do with the data that is returned from that post. How do I then add that new persisted record to the select list?
I know the tag isn't passing to the controller method as it's not bound to any sort of model but being as I'm using a view model on the parent view, I'm not sure how I would handle that here either.
In order to dynamically add a new BlogTag in the view you will need to post the new tag Name using ajax, to a controller method that saves the BlogTag and returns its new ID value. Your controller method would be something like
[HttpPost]
public JsonResult CreateTag(string name)
{
BlogTag tag = new BlogTag(){ Name = name };
db.BlogTags.Add(tag);
db.SaveChanges();
return Json(tag.ID);
// If the above code could result in an error/exception, catch it and return
// return Json(null);
}
Then in the view, handle the dialogs submit button to post the value and update the tag list
var url = '#Url.Action("CreateTag")';
var tagList = $('#SelectedTags');
$('#tag-form').submit(function() {
var tagName = $('#Name').val();
$.post(url, { name: tagName }, function(id) {
if (id) {
// add the new tag to the list box
tagList.append($('<option></option>').val(id).text($('#Name').val()));
// trigger the chosen update
tagList.trigger("chosen:updated");
} else {
// Oops - display an error message?
}
}).fail(function (result) {
// Oops - display an error message?
});
return false; // cancel the default submit
});
Side note: I would recommend that you create a view model for BlogTagVM (containing a property for the Name with validation attributes) and an associated partial view (say _AddBlogTag.cshtml) that generates the dialog html, so that in the main view you can use #Html.Partial("_AddBlogTag", new BlogTagVM()) which will allow you to use the strongly typed html helpers, and to include client side validation.
Note also that nested <form> elements are invalid html so ensure that html for the dialog is outside the main <form> tag for the view.
I am doing something similar, I think it might help. In my case, I'm "moving" values from one list to another (from "available" to "used") and then saving the values of the "used" list. Anyway, in the controller, the "used" list shows up as an array of strings. Here's my code:
public ActionResult PinchHit(FormCollection form, LineupViewModel lvm, String[] UsedPlayers)
{
[Snip]
if (ModelState.IsValid && lineupResults.IsValid)
{
[Snip]
foreach (String usedID in UsedPlayers)
{
gameState.HomeUsedPlayersIDs.Add(Convert.ToInt32(usedID));
}
uow.Repository<GameState>().Update(gameState);
uow.SaveChanges();
return RedirectToAction("Index", "GameSummary");
}
[Snip]
return View(lvm2);
}
Hope that helps.
Per my comment:
Here is an AJAX call-back mechanism I used to retrieve data from the database without reloading the page, you could use it to save data to the database instead.
<script type="text/javascript">
function getPositions(id, control) {
$.ajax({
url: "#Url.Action("GetPositions", "Lineup")",
data:
{
id: id
},
dataType: "json",
type: "POST",
error: function () {
alert("An error occurred.");
},
success: function (data) {
$(control).html("");
$.each(data, function (i, item) {
$(control).append("<option value=\"" + item.Value + "\">" + item.Text + "</option>");
}
);
}
});
}
</script>
then in the controller:
[HttpPost]
public ActionResult GetPositions(int id)
{
Player player = uow.Repository<Player>().GetById(id);
if (player == null)
{
return (null);
}
List<SelectListItem> positionList = new SelectList(player.Positions, "ID", "ShortName").ToList();
return Json(positionList);
}
Pretty standard stuff really.
Hello I'm new to cshtml and I have web pages in ASP.NET Razor v2 I would like to insert some data into DB on button click. These data are provided from various textboxes and also uploading picture. May I please know how to how to provide action on button click?
I tried this in my cshtml file :
<button type="submit" name="action" value="insertRegistered">Uložit</button>
#if (action == "insertRegistered")
{
var db1 = Database.Open("StarterSite");
var sql = "UPDATE services SET FileName=#0, FileContent=#1, MimeType=#2 WHERE IDservice=6";
db1.Execute(sql, fileName, fileContent, fileMime);
}
In WebMatrix, you can accomplish this in this way:
Razor code:
#{
var fileName = "";
var fileContent = "";
var fileMime = "";
var IDservice = "";
#*TEST CODE *#
#*if (!IsPost)
{
IDservice = "1";
var db = Database.Open("StarterSite");
var dbCommand = "SELECT * FROM services WHERE IDservice = #0";
var row = db.QuerySingle(dbCommand, IDservice);
fileContent = row.fileContent;
fileMime = row.MimeType;
fileName = row.fileName;
} *#
if (IsPost)
{
fileName = Request.Form["fileName"];
fileContent = Request.Form["fileContent"];
fileMime = Request.Form["fileMime"];
IDservice = Request.Form["IDservice"];
var db1 = Database.Open("StarterSite");
var sql = "UPDATE services SET FileName=#0, FileContent=#1, MimeType=#2 WHERE IDservice=#3";
db1.Execute(sql, fileName, fileContent, fileMime, IDservice);
}
}
And the markup should look like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Service</title>
</head>
<body>
<form method="post">
<fieldset>
<legend>Service Information</legend>
<p><label for="fileName">FileName:</label>
<input type="text" name="fileName" value="#fileName" /></p>
<p><label for="fileContent">File Content:</label>
<input type="text" name="fileContent" value="#fileContent" /></p>
<p><label for="fileMime">Mime:</label>
<input type="text" name="fileMime" value="#fileMime" /></p>
<input type="hidden" name="IDservice" value="#IDservice" />
<p> <button type="submit" name="action" value="insert Registered">Uložit</button></p>
</fieldset>
</form>
</body>
</html>
And here's a working sample.
Here's a set of tutorials which, I believe, should be very helpful!
Put your database logic into a controller action, like this:
public class HomeController : Controller
{
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// Do database update logic here
// Upon successfully updating the database redirect to a view
// that displays the information, read-only version not editable
return RedirectToAction("Index");
}
catch(Exception ex)
{
// If something went wrong, then re-display the view
// the user tried to update database from
return View();
}
}
}
Now in your view create a form by using the HTML helper Html.BeginForm(), like this:
#using (Html.BeginForm("ActionMethodName","ControllerName"))
{
... your input, labels, textboxes and other html controls go here
<input class="button" id="submit" type="submit" value="Uložit" />
}
Note: Html.BeginForm() will take everything inside of it and submit that as the form data to the controller action specified as parameters to it.