I'm new to MVC so I hope to get help regarding my question. I am making users upload images. the image path will store in the database but the image itself will store in the Content folder. The code is working fine (which means there is no error) but I don't get the wanted result. I appreciate your help. Thanks in advance.
Here is the Controller code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "EmployeeId,EmpName,EmpEmail,Poition,Nationality,Last_W_D,EmpHOD,Password,DepId,SignaturePath,DoctorCategory")] Tbl_Employee tbl_Employee, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if(file != null)
{
file.SaveAs(HttpContext.Server.MapPath("~/Content/Images/Employees/") + file.FileName);
tbl_Employee.SignaturePath = file.FileName;
}
db.Tbl_Employee.Add(tbl_Employee);
db.SaveChanges();
return RedirectToAction("Index");
}
Here is the "Create view " code:
#model ClearanceFirst.Models.Tbl_Employee
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("Create", "Tbl_Employee", null, FormMethod.Post, new { enctype = "
multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Tbl_Employee</h4>
<hr />
<div class="form-group">
#Html.LabelFor(model => model.SignaturePath, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input id="signaturePath " title ="upload images " type="file" name="file" />
#Html.ValidationMessageFor(model => model.SignaturePath, "", new { #class = "text-danger" })
</div>
</div>
Here is the "Index view" code:
<td>
#if (!string.IsNullOrWhiteSpace(item.SignaturePath))
{
<img width = "70" height = "50"
src="~/Content/Images/Employees/#Url.Content(item.SignaturePath)"
alt= "Alternate Text"/> }
</td>
The uploaded Images will be converted to Binary format then saved to SQL Server Database table.
Check the below given links for more information, how to upload and retrieve Images from Sql Server in ASP.NET MVC,
Save and Retrieve Image from SQL Server Database in ASP.Net MVC.
Store an Image URL in database and use it in ASP.NET MVC.
Related
I'm building a web API and I want to consume it through an MVC view. The API controller is to insert the user data and the MVC controller is to create the view. I have been looking for information and this is what I have been able to do with that information.
So, the API controller, simply inserts the data to the database through an stored procedure, I've tested with Postman and works fine:
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
[HttpPost]
public IActionResult post(Models.Request.UserModel model)
{
using (Models.AdminOrchardContext db = new Models.AdminOrchardContext())
{
Models.UserModel oUsuar = new Models.UserModel();
Models.OrchardTable tOrchard = new Models.OrchardTable();
oUsuar.Name = model.Name;
oUsuar.Email = model.Email;
tOrchard.OrchardLocation = model.OrchardLocation;
var uName = new SqlParameter("#name", oUsuar.Name);
var uEmail = new SqlParameter("#email", oUsuar.Email);
var hOrchardLocation = new SqlParameter("#OrchardLocation", tOrchard.OrchardLocation);
var idUserReg = db.Usuarios.FromSqlRaw("Exec UserAndOrchardInsert #name, #email" +
"#OrchardLocation",
new[] { uName, uEmail, hOrchardLocation});
db.SaveChanges();
}
return Ok();
}
}
The MVC controller where the view is added, from here the API is used with the user data on the view:
[HttpPost]
public IActionResult post(Models.Request.User model)
{
HttpClient hc = new HttpClient();
hc.BaseAddress = new Uri("https://localhost:44325/api/User");
var addRecToDB = hc.PostAsJsonAsync<Models.Request.User>("User", model);
addRecToDB.Wait();
ViewBag.message = "Ok!";
return View();
}
And the view:
#model Huerbog.Models.Request.User
#{
ViewData["Title"] = "post";
}
<h1>User registration</h1>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<h4>Orchard-related field</h4>
<div class="form-group">
<label asp-for="OrchardLocation" class="control-label"></label>
<input asp-for="OrchardLocation" class="form-control" />
<span asp-validation-for="OrchardLocation" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
<h4>#ViewBag.message</h4>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Now, the problem is that when I open the view, even when the API is running, on the page appears the Error 405, I don't know what or where exactly is the error.
the problem is that when I open the view, even when the API is running, on the page appears the Error 405, I don't know what or where exactly is the error.
Please note that your action post contains the [HttpPost] attribute, which constrains matching to HTTP Post request(s) only.
While you enter URL to access https://xxx/controller_name/post from browser side, browser would help make HTTP Get request to server, which cause 405 Method Not Allowed error.
To fix it, you can try to add a HttpGet post method to make the endpoint support HTTP Get method request(s), like below.
[HttpGet]
public IActionResult post()
{
return View();
}
[HttpPost]
public IActionResult post(Models.Request.User model)
{
//...
I am attempting to get data via a call to a WebApi within AngularJS. I have verified the service works and I am getting the correct data.
The problem(s) are that the selected item is not appearing AND the binding to the model for the result does not appear to be working.
I am a relative newbie in terms of AngularJS. Can somebody please tell me what I am doing wrong and how to correct the issues?
Thanks in advance!
Here is the angular code:
var app = angular.module("GreatWestSoftware", [])
app.controller("ContactMeByController",
function ($scope, $http ,$window) {
function GetContactByMethods($http) {
//$scope.Message = 'NULL';
//$scope.employees = {};
$http.get('http://localhost:53350/api/ContactBy').then(function (response) {
$scope.ContactByMethods = response.data;
$scope.Message = 'OK';
$scope.gotdata = true;
},
function (err) {
$scope.Message = 'Call failed' + err.status + ' ' + err.statusText;
$scope.ContactByMethods = {};
$scope.gotdata = false;
}
);
//window.setTimeout(function () {
// $scope.gotdata = true;
//}, 1000);
};
function ShowAlert(msg)
{
$window.alert(msg);
}
}
);
Here is the model from MVC:
public class SurveyAnswersHeaderViewModel
{
public int ProductID { get; set; }
[Required]
[Display(Name = "Name:")]
public string Name { get; set; }
[EmailAddress]
[Display(Name = "Your Email Address:")]
public string Email { get; set; }
[Phone]
[Display(Name = "Phone Number:")]
[DataType(DataType.PhoneNumber,ErrorMessage ="Invalid Phone Number")]
public string Phone { get; set; }
[Required]
[Display(Description ="How should you be contacted",Name ="Contact Me By:",Prompt ="Select contact method")]
public int ContactBy { get; set; }
}
Here is the page I am attempting to load:
#model GreatWestSoftware.Models.SurveyAnswersHeaderViewModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Great West Software Site Survey";
}
#using (Html.BeginForm("Create", "SurveyAnswersHeader", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>#ViewBag.SurveyName</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.HiddenFor(m => m.ProductID)
</div>
<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.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Phone, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Phone, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Phone, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div ng-app="GreatWestSoftware" ng-controller="ContactMeByController" ng-show="DisplayContactBy">
#Html.LabelFor(model => model.ContactBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10" >
<select id="ContactByDropdown" ng-model="ContactBy" class="form-inline">
<option ng-repeat="ContactByoption in ContactByMethods" ng-selected="{{ContactByoption.IsSelected==true}}" value="{{ContactByoption.ContactByID}}">{{ContactByoption.ContactMeBy}}</option>
</select>
#*#Html.EditorFor(model => model.ContactBy, new { htmlAttributes = new { #class = "form-control" } })*#
#Html.ValidationMessageFor(model => model.ContactBy, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div>
<h4 class="text-danger">#ViewBag.ErrorMessages</h4>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Start Survey" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Skip", "Index","Home")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/GreatWestSoftware.js"></script>
}
I do get the values of the dropdown. But oddly, in the generated code there is a . I'm guessing that this is showing up as the blank entry in the list. The dropdown is also not showing the selected initial value, even though the html seems correct.
The second problem is that on the submittal of the form, the selected value is not being bound to the MVC model.
Here is what appears in the dropdown. The correct data...
Here is the generated html code
The dropdown is not showing the inital value because the value is being initialiazed after the select is created. To fix this you need to load the values on the resolve of your route.
Example:
$routeProvider
.when("/state-name", {
templateUrl: "your-template.html",
controller: "ContactMeByController",
resolve: {
contactByMethodsPromise: function($http){
return $http.get('http://localhost:53350/api/ContactBy');
}
}
})
And in your controller:
app.controller("ContactMeByController",
function ($scope, $http , $window, contactByMethodsPromise) {
$scope.ContactByMethods = contactByMethodsPromise;
}
This should fix the select initial value.
About it not binding, I'm not sure Angular binds it to the MVC Model. It is binding to the variable $scope.ContactBy, which you can then submit to your API.
Also, you should consider using only Angular to render your pages, it's not necessary and will probably cause strange behaviours mixing it with ASP.NET, as you can see here.
I'm trying to make a website using asp.net mvc 4 & Entity Framework 6 & the database is SQL Server 2012. I have a column in UserPassword table where all the passwords are encrypted like this, D1-24-0F-FB-16-AA-A9-CB-50-22-18-8D-E4-AF-59-CA. I want to use these datas for login in the website. I've tried but not working.
This is my code:
Controller
public class HomeController : Controller
{
abncodbEntities db = new abncodbEntities();
[HttpPost]
public ActionResult Login(UserPassword id)
{
if (ModelState.IsValid)
{
var uservar = db.UserPasswords.Where(a => a.UserId.Equals(id.UserId) && a.Password.Equals(id.Password)).FirstOrDefault();
if (uservar != null)
{
Session["UserBOID"] = uservar.UserId.ToString();
return RedirectToAction("UserLogin");
}
}
return View(id);
}
}
View
#model ABCoLtd.Models.UserPassword
using (Html.BeginForm("Login", "Home", FormMethod.Post)) {
#Html.ValidationSummary(true)
<div class="editor-label">
<strong>Enter your ID</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.UserId)
#Html.ValidationMessageFor(a => a.UserId)
</div>
<div class="editor-label">
<strong>Password</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.Password)
#Html.ValidationMessageFor(a => a.Password)
</div><br />
<p><input type="submit" class="btn btn-info" value="Login" /></p>
}
If I only try with ID then it works but not working with password. How can I use the passwords for login? I'm new in this situation. Any help would be appreciated. Thanks.
I am currently using MEAN.js to create an app and I scaffolded a simple entity called Campaign. I would like each Campaign to have a picture associated. Therefore, I would like to change the CRUD interface to be able to upload a file to the back end.
I injected the ng-file-upload plugin to create the FE with Angular. On the Node.js side, I installed the multer plugin to help me save the file into a folder (e.g. ./uploads). The thing is that I do not quite get the flow and I was hoping for a suggestion.
Please, find below the view:
<section data-ng-controller="CampaignsController">
<div class="page-header">
<h1>New Campaign</h1>
</div>
<div class="col-md-12">
<form class="form-horizontal" data-ng-submit="create()" novalidate>
<fieldset>
<div class="form-group">
<label class="control-label" for="name">Name</label>
<div class="controls">
<input type="text" data-ng-model="name" id="name" class="form-control" placeholder="Name" required>
</div>
</div>
<div class="form-group">
<button ng-file-select ng-model="token">Upload the token</button>
<div ng-file-drop ng-model="token" class="drop-box"
drag-over-class="{accept:'dragover', reject:'dragover-err', delay:100}"
accept="image/*">
Drop image file here
</div>
<div ng-no-file-drop>Image drop is not supported for this browser.</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-default">
</div>
<div data-ng-show="error" class="text-danger">
<strong data-ng-bind="error"></strong>
</div>
</fieldset>
</form>
</div>
</section>
Then, the Angular controller action:
// Create new Campaign
$scope.create = function() {
// Create new Campaign object
var campaign = new Campaigns ({
name: this.name
});
$scope.$watch('token', function() {
$scope.upload = $upload.upload({
url: '/campaigns', //upload.php script, node.js route, or servlet url
method: 'POST', //Post or Put
headers: {'Content-Type': 'multipart/form-data'},
//withCredentials: true,
data: campaign, //from data to send along with the file
file: $scope.token, // or list of files ($files) for html5 only
//fileName: 'photo' // to modify the name of the file(s)
}).success(function (response, status) {
// Redirect after save
campaign.$save(function(response) {
$location.path('campaigns/' + response._id);
// Clear form fields
$scope.name = '';
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
}
).error(function (errorResponse) {
$scope.error = errorResponse.data;
//$scope.error = errorResponse.data.message;
});
});
};
Finally, the Node.js controller portion:
var mongoose = require('mongoose'),
errorHandler = require('./errors'),
multer = require('multer'),
Campaign = mongoose.model('Campaign'),
_ = require('lodash');
/**
* Create a Campaign
*/
exports.create = function(req, res) {
var campaign = new Campaign(req.body);
campaign.user = req.user;
multer({
dest: './uploads/'
});
campaign.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(campaign);
}
});
};
Right now, what happens is that - when I try to upload a file - the uploader does not wait for the file to be selected, but it sends the POST request immediately (why?). Moreover, I get a 400 response.
Any suggestion would be really appreciated!
Thanks
Cheers
I partially solved the problem.
This is the new view:
<section data-ng-controller="CampaignsController">
<div class="container">
<div class="page-header">
<h1>New Campaign</h1>
</div>
<div class="col-sm-12 col-md-4 col-md-offset-4">
<form class="form-horizontal" data-ng-submit="create(token)" novalidate>
<fieldset>
<div class="form-group">
<label class="control-label" for="name">Name</label>
<div class="controls">
<input type="text" data-ng-model="name" id="name" class="form-control" placeholder="Name" required>
</div>
</div>
<div class="form-group">
<label class="control-label" for="token">Token</label>
<div class="controls">
<input type="file" id="token" ng-file-select ng-model="token"/>
<p class="help-block">The token file must be a squared .png or .jpg image.</p>
</div>
</div>
<div class="form-group">
<div class="controls">
<input type="submit" class="btn btn-default col-xs-12">
</div>
</div>
<div class="form-group">
<div data-ng-show="error" class="control alert alert-danger alert-dismissible" role="alert">
<span data-ng-bind="error"></span>
</div>
</div>
</fieldset>
</form>
</div>
</div>
</section>
Then, the Angular controller action:
$scope.create = function(token) {
// Create new Campaign object
var campaign = new Campaigns ({
name: this.name
});
$scope.upload = $upload.upload({
url: '/campaigns',
method: 'POST',
headers: {'Content-Type': 'multipart/form-data'},
//withCredentials: true,
data: {
campaign: JSON.stringify(campaign)
},
file: token,
//fileName: 'token' // to modify the name of the file
}).success(function (response, status) {
// Redirect after save
$location.path('campaigns/' + response._id);
// Clear form fields
$scope.name = '';
$scope.token = '';
}
).error(function (errorResponse) {
$scope.error = errorResponse.data;
}
);
};
I am now using node multiparty for the Node.js controller:
exports.create = function(req, res) {
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
//res.writeHead(200, {'content-type': 'text/plain'});
//res.end(util.inspect({fields: fields, files: files}));
var file = files.file[0];
var contentType = file.headers['content-type'];
var tmpPath = file.path;
var extIndex = tmpPath.lastIndexOf('.');
var extension = (extIndex < 0) ? '' : tmpPath.substr(extIndex);
// uuid is for generating unique filenames.
//var fileName = uuid.v4() + extension;
var fileName = tmpPath;
var destPath = 'uploads/' + fileName;
// Server side file type checker.
if (contentType !== 'image/png' && contentType !== 'image/jpeg') {
fs.unlink(tmpPath);
return res.status(400).send({
message: 'Unsupported file type'
});
}
fs.rename(tmpPath, destPath, function(err) {
if (err) {
return res.status(400).send({
message: 'Image is not saved'
});
}
fs.unlink(tmpPath, function() {
if (err) {
return res.status(400).send({
message: 'Impossible to delete temp file'
});
}
});
console.log(destPath);
//return res.jsonp(destPath);
});
var campaign = new Campaign(JSON.parse(fields.campaign[0]));
campaign.user = req.user;
campaign.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(campaign);
}
});
});
};
I still get an error, but I do not think is related with the file upload. What do you think?
/home/maurizio/Workspace/bdf-v1/node_modules/mongoose/lib/utils.js:413
throw err;
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:691:11)
at ServerResponse.header (/home/maurizio/Workspace/bdf-v1/node_modules/express/lib/response.js:592:10)
at ServerResponse.send (/home/maurizio/Workspace/bdf-v1/node_modules/express/lib/response.js:144:12)
at ServerResponse.jsonp (/home/maurizio/Workspace/bdf-v1/node_modules/express/lib/response.js:301:15)
at Promise. (/home/maurizio/Workspace/bdf-v1/app/controllers/campaigns.server.controller.js:67:9)
at Promise. (/home/maurizio/Workspace/bdf-v1/node_modules/mongoose/node_modules/mpromise/lib/promise.js:177:8)
Using res.status(400).send... or res.jsonp() will send data back to the client starting with the headers. Your script has these statements falling through, but the subsequent ones cannot be executed since data has already been sent to the client.
The returns you have will end the execution of the method they're invoked in, but the script will just continue to the next method where it will encounter another express send(). In your case, fs.rename will send() the 400, but will encounter another send() when it reaches the campaign.save method where it will throw the error.
Take your calls of return res.status(400).send(), and instead set the message as a string variable, and make the res.status(400).send() call in your final conditional statement if an error is present.
Essentially, make sure a send() or jsonp() invocation can only be made once in your script.
I followed the following tutorial (https://code.tutsplus.com/tutorials/laravel-4-a-start-at-a-restful-api-updated--net-29785) to create a REST API with Laravel. Here we're creating a new Url which gets two inputs: a url and description and stores it to a database.
public function store()
{
$url = new Url;
$url->url = Request::get('url');
$url->description = Request::get('description');
$url->user_id = Auth::user()->id;
$url->save();
return Response::json(array(
'error' => false,
'urls' => $urls->toArray()),
200
);
}
In trying to teach myself AngularJS, I've been trying to connect this REST API with an AngularJS front end. Here's my form:
<form data-ng-controller="formController">
<p>Store a URL To Read Later:</p>
<div class="form-group">
<input class="form-control" type="text" placeholder="Enter URL here" data-ng- model="newurl" />
</div>
<p>Description:</p>
<div class="form-group">
<input class="form-control" type="text" placeholder="Enter a brief description" data-ng-model="newdescription" />
</div>
<div class="form-group text-right">
<button class="btn btn-success" data-ng-click="submitUrl()">Add To List</button>
</div>
</form>
The data-ng-click is calling the submitUrl function which I have defined in the FormController.
function formController($scope, $http) {
$scope.submitUrl = function() {
var data = { 'url': $scope.newurl, 'description': $scope.newdescription };
$http.post("http://readitlater.loc/api/v1/url/", data )
}
}
I guess I'm puzzled as to how to get the input data to the public function store() and what kind of data it's expecting. Thanks for your time.
I figured it out. Rewriting like this, solved the problem.
function formController($scope, $http) {
$scope.submitUrl = function() {
var data = { 'url': $scope.newurl, 'description': $scope.newdescription };
$http({
method: 'POST',
url: 'http://readitlater.loc/api/v1/url/',
headers: { 'Content-Type' : 'application/x-www-form-urlencoded'},
data: $.param(data)
});
AngularJS sends POST requests with application/json type & JSON body by default. I'm not familiar with Laravel, but looks like using Input instead of Request is what you need: http://laravel.com/docs/4.2/requests#basic-input