Uploading file and posting text input values in one click? - javascript

I'm trying build an Asp.net web api for posting files. I found the following example in
https://code.msdn.microsoft.com/AngularJS-with-Web-API-22f62a6e
The Web API method is:
[RoutePrefix("api/photo")]
public class PhotoController : ApiController
{
private IPhotoManager photoManager;
public PhotoController()
: this(new LocalPhotoManager(HttpRuntime.AppDomainAppPath + #"\Album"))
{
}
public PhotoController(IPhotoManager photoManager)
{
this.photoManager = photoManager;
}
// GET: api/Photo
public async Task<IHttpActionResult> Get()
{
var results = await photoManager.Get();
return Ok(new { photos = results });
}
// POST: api/Photo
public async Task<IHttpActionResult> Post()
{
// Check if the request contains multipart/form-data.
if(!Request.Content.IsMimeMultipartContent("form-data"))
{
return BadRequest("Unsupported media type");
}
try
{
var photos = await photoManager.Add(Request);
return Ok(new { Message = "Photos uploaded ok", Photos = photos });
}
catch (Exception ex)
{
return BadRequest(ex.GetBaseException().Message);
}
}
And the file uploader html code: (I added a text input <input type="text" id="test" value="testit" /> for test.
<form name="newPhotosForm" role="form" enctype="multipart/form-data" ng-disabled="appStatus.busy || photoManagerStatus.uploading">
<div class="form-group" ng-hide="hasFiles">
<label for="newPhotos">select and upload new photos</label>
<input type="file" id="newPhotos" class="uploadFile" accept="image/*" eg-files="photos" has-files="hasFiles" multiple>
<input type="text" id="test" value="testit" /> <!--- Added a text input for test -->
</div>
<div class="form-group" ng-show="hasFiles && !photoManagerStatus.uploading">
<ul class="list-inline">
<li><strong>files:</strong></li>
<li ng-repeat="photo in photos"> {{photo.name}}</li>
</ul>
<input class="btn btn-primary" type="button" eg-upload="upload(photos)" value="upload">
<input class="btn btn-warning" type="reset" value="cancel" />
</div>
<div class="form-group" ng-show="photoManagerStatus.uploading">
<p class="help-block">uploading</p>
</div>
</form>
The JS upload function:
function upload(photos)
{
service.status.uploading = true;
appInfo.setInfo({ busy: true, message: "uploading photos" });
var formData = new FormData();
angular.forEach(photos, function (photo) {
formData.append(photo.name, photo);
});
return photoManagerClient.save(formData)
.$promise
.then(function (result) {
if (result && result.photos) {
result.photos.forEach(function (photo) {
if (!photoExists(photo.name)) {
service.photos.push(photo);
}
});
}
appInfo.setInfo({message: "photos uploaded successfully"});
return result.$promise;
},
function (result) {
appInfo.setInfo({message: "something went wrong: " + result.data.message});
return $q.reject(result);
})
['finally'](
function () {
appInfo.setInfo({ busy: false });
service.status.uploading = false;
});
}
However, it seems the value of the added input test cannot be passed to the Web API code?

You need to add custom DTO/POCO class, set the values and then pass it as parameter to your post method. Since file is not a simple type default MediaTypeFormatter of webAPI won't work so you need to build your custom MediaTypeFormatter.
Sample POCO class
Public Class Attachment
{
public string Input {get;set;}
public byte[] Content{get;set;}
}
Custom Media formatter as below
public class CustomFormatter : MediaTypeFormatter
{
/// <summary>
///
/// </summary>
public CustomFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));
}
public override bool CanReadType(Type type)
{
return type == typeof(Attachment);
}
public override bool CanWriteType(Type type)
{
return false;
}
public async override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var provider = await content.ReadAsMultipartAsync();
var modelContent = provider.Contents
.FirstOrDefault(c => c.Headers.ContentType.MediaType == "application/json");
var attachment = await modelContent.ReadAsAsync<Attachment>();
var fileContents = provider.Contents
.Where(c => c.Headers.ContentType.MediaType == "image/jpeg").FirstOrDefault(); // or whatever is the type of file to upload
attachment.Content = await fileContents.ReadAsByteArrayAsync();
return attachment;
}
}
Register the custom media formatter:
private void ConfigureWebApi(HttpConfiguration config)
{
//other code here
config.Formatters.Add(new CustomFormatter());
}
Pass the POCO to your Web-API Controller
public async Task<IHttpActionResult> Post(Attachment attachment)
{
I haven't tested this in Visual Studio, but this is the approach you need to follow
More information here:
http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters
And a sample here
http://blog.marcinbudny.com/2014/02/sending-binary-data-along-with-rest-api.html#.V5MDDzV7qYg

Related

Insert Category data in mvc using jquery

my java code is not working when pulling data in database.
Where am I going wrong? I tried many times but it didn't work.
I'm looking at debug mode mastercontroller. data is not coming.
I have jquery.min.js attached on my layout page.
I tried another js code as a trial, it works. I'm waiting for your help
My java code is not working when adding category array to mvc using jquery
//categoryaddt.js
$(document).ready(function () {
$("#categoryform").validate({
rules: {
Name: { required: true },
},
messages: {
Nanem: "Please Enter a Valid Name."
},
submitHandler: function (e) {
var chk = 0;
if ($("#closeButton").prop('checked') == true) {
chk = 1;
}
var RequestCls = {
Name: $("#txtName").val(),
Active: chk
}
var UrlApi = '#Url.Content("~")' + "Master/AddCategory";
$.ajax({
url: UrlApi,
type: 'POST',
data: JSON.stringify(RequestCls),
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert(data.message);
},
error: function (data) {
alert(data.message);
}
});
}
})
});
//Category.cshtml
#{
ViewBag.Title = "Category";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row">
<div class="row">
<div class="card">
<div class="card-body">
<form id="categoryform" method="post">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="Name">Name</label>
<input id="txtName" name="Name" type="text" class="form-control" autocomplete="off" />
</div>
<div class="custom-control custum-checkbox mb-2">
<input type="checkbox" class="custom-control-input input-mini" id="closeButton" value="checked" />
<label class="custom-control-label" for="closeButton">Is Active</label>
</div>
</div>
</div>
<button type="submit" id="btnSave" class="btn btn-primary mr-1 waves-effect waves-light"></button>
</form>
</div>
</div>
</div>
</div>
#section scripts{
<script src="~/Scripts/categoryaddt.js"></script>
}
//MasterCls.cs
using Nero_Medya_Inventory_Management_System.BusinessLogic.IService;
using Nero_Medya_Inventory_Management_System.Utility.RequestCls;
using Nero_Medya_Inventory_Management_System.Utility.Responsecls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Nero_Medya_Inventory_Management_System.BusinessLogic.ServiceCls
{
public class MasterCls : IMaster
{
QrperidEntities dbEntity;
public MasterCls()
{
dbEntity = new QrperidEntities();
}
public ResponseCls AddCategory(RequestCls obj)
{
ResponseCls result = new ResponseCls();
result.message = "Kayıt Başarı ile Yapıldı...!";
result.status = "succes";
result.flag = 1;
try
{
using (var db = dbEntity)
{
Category _category = new Category();
_category.Name = obj.Name;
_category.Active = obj.Active;
db.Category.Add(_category);
db.SaveChanges();
}
}
catch (Exception ex)
{
result.message = ex.Message.ToString();
result.status = "error";
result.flag = 0;
}
return result;
}
}
}
//IMaster.cs
using Nero_Medya_Inventory_Management_System.Utility.RequestCls;
using Nero_Medya_Inventory_Management_System.Utility.Responsecls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nero_Medya_Inventory_Management_System.BusinessLogic.IService
{
public interface IMaster
{
ResponseCls AddCategory( RequestCls obj );
}
}
//Category.cs
//------------------------------------------------------------------------------
// <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 Nero_Medya_Inventory_Management_System
{
using System;
using System.Collections.Generic;
public partial class Category
{
public int Id { get; set; }
public string Name { get; set; }
public Nullable<int> Active { get; set; }
}
}
//MasterController.cs
using Nero_Medya_Inventory_Management_System.BusinessLogic.IService;
using Nero_Medya_Inventory_Management_System.BusinessLogic.ServiceCls;
using Nero_Medya_Inventory_Management_System.Utility.RequestCls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Nero_Medya_Inventory_Management_System.Controllers
{
public class MasterController : Controller
{
// GET: Master
IMaster _master;
public MasterController()
{
_master = new MasterCls();
}
public ActionResult Category()
{
return View();
}
[HttpPost]
public JsonResult AddCategory(RequestCls obj)
{
var result = _master.AddCategory(obj);
return Json(result,JsonRequestBehavior.AllowGet);
}
}
}

Multiple forms in #foreach loop. How do I submit one asynchronously with javascript. C# core Razor

Shopping cart with many items how to remove any item asynchronously with JavaScript this is my work so far. Can anyone improve on this?
your help would be greatly appreciated. Have a great day
Ok so this works if you remove items from the top of the list but fails if you remove items from some other place.
The problem seems to be that the form names are all the same "remove" without any indexing.
Problem is I'm not sure how to proceed with this.
document.forms['remove'].onsubmit = () => {
let formData = new FormData(document.forms['remove']);
fetch('/sales/cart?handler=RemoveItem', {
method: 'post',
body: new URLSearchParams(formData)
})
.then(() => {
var url = "/sales/cart?handler=CartPartial";
console.log(url)
$.ajax({
url: url,
success: function (data) {
$("#exampleModal .modal-dialog").html(data);
$("#exampleModal").modal("show");
//alert('Posted using Fetch');
}
});
});
return false;
}
<pre>
#foreach (var item in Model.Items)
{
<form name="remove" method="post">
<h4 class="text-left text-body">#item.Price.ToString("c")
<button class="btn btn-sm" title="Trash"><i style="font-size:large"
class="text-warning icon-Trash"></i></button>
</h4>
<input type="hidden" asp-for="#Model.Id" name="cartId" />
<input type="hidden" asp-for="#item.Id" name="cartItemId" />
</form>
}
</pre>
Update
----------
New markup
I added an index to the id and included an onclick event.
<form method="post" id="#i" onclick="removeItem(this.id)">
<button class="btn btn-sm" title="Trash">Item One</button>
<input type="hidden" asp-for="#Model.Id" name="cartId" />
<input type="hidden" asp-for="#item.Id" name="cartItemId" />
</form>
and create a new function that captured the form id including it in a constant.
<script>
function removeItem(formId) {
const form = document.getElementById(formId);
form.onsubmit = () => {
let formData = new FormData(form);
fetch('/sales/cart?handler=RemoveItem', {
method: 'post',
body: new URLSearchParams(formData)
})
.then(() => {
var url = "/sales/cart?handler=CartPartial";
console.log(url)
$.ajax({
url: url,
success: function (data) {
$("#exampleModal .modal-dialog").html(data);
$("#exampleModal").modal("show");
//alert('Posted using Fetch');
}
});
});
return false;
}
}
</script>
If anybody can improve on this please post it here.
Thanks.
Updates code behind Cart.cshtml.cs
using System;
using System.Threading.Tasks;
using Malawby.Models;
using Malawby.Services.Interfaces;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Malawby.Pages.Sales
{
public class CartModel : PageModel
{
private readonly ICartRepository _cartRepository;
public CartModel(ICartRepository cartRepository)
{
_cartRepository = cartRepository ?? throw new
ArgumentNullException(nameof(cartRepository));
}
[BindProperty]
public Cart Cart { get; set; } = new Cart();
public const string SessionKeyName = "_Name";
public string SessionInfo_Name { get; private set; }
public void OnGetAsync()
{
}
public async Task<PartialViewResult> OnGetCartPartialAsync()
{
var userName = GetUserName();
if (userName != null)
{
Cart = await _cartRepository.GetCartByUserName(userName);
}
return Partial("_ToCart", model: Cart);
}
private string GetUserName()
{
return HttpContext.Session.GetString(SessionKeyName);
}
public async Task OnPostRemoveItemAsync(int cartId, int cartItemId)
{
await _cartRepository.RemoveItem(cartId, cartItemId);
}
}
}
Update 2
This is the modified code I used. This is the error in the console.
XML Parsing Error: no root element found Location: localhost:44331/sales/cart?handler=RemoveItem Line Number 1, Column 1
There is no error on the page just nothing happens on the click of the trash can.
<script type="text/javascript">
function removeItem(cartItemId, cardId) {
var removeUrl = "/sales/cart?handler=RemoveItem";
$.post(removeUrl,
{
cartItemId: cartItemId,
cardId: cardId
})
.done(function (data) {
alert(data); //usually return true or false if true
remove card
$('#card_' + cardId).remove();
});
}
</script>
I am not familiar with asp.net core, but I will show how I usually do it without focusing on syntax.
first on the view no need to add multiple form but should use card id as index and delete button sent selected index like this:
#foreach (var item in Model.Items)
{
<div id="card_#item.cardId">
<h4 class="text-left text-body">#item.Price.ToString("c")
<button class="btn btn-sm" onclick="removeItem('#item.cardId') title="Trash"><i style="font-size:large"
class="text-warning icon-Trash"></i></button>
</h4>
</div>
}
then the script function will call remove api and remove selected card with no need to re-render the page:
<script type="text/javascript">
function removeItem(cardId) {
var removeUrl = "your apiUrl";
$.post( "removeUrl", { cardId: cardId })
.done(function( data ) {
alert( data ); //usually return true or false if true remove card
$('#card_'+ cardId).remove();
});
}
</script>

Deleting items from dynamic list ASP Core MVC

I'm trying to remove or hide items from a list and I'm facing two problems, 1- the newly cannot be removed, 2- Tried to tag the deleted items as isDeleted = true using Javascript then later delete them in the controller following this answer https://stackoverflow.com/a/40572625/10773318 but it didn't work.
Here's my view models
public class CreateEditParentViewModel
{
public int Id { get; set; }
public IList<ChildViewModel> ChildrenLists { get; set; }
}
public class ChildViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool isDeleted { get; set; }
}
In the main view
<div id="editorRows">
#foreach (var item in Model.ChildrenLists)
{
<partial name="_RowPartial" model="item" />
}
</div>
<a id="addItem" asp-action="BlankRow" asp-controller="Home">Add Row...</a> <br />
<input type="submit" value="Finished" />
The javascript in the main view
#section scripts {
<script>
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) { $("#editorRows").append(html); }
});
return false;
});
$("a.deleteRow").click(function () {
$(this).parents("div.editorRow:first").remove(); //does not work with newly added
return false;
}); //what it should do: hide and set isDeleted = true if id is not null - remove if null
</script>
Finally the partial view
<div class="editorRow">
#using (Html.BeginCollectionItem("ChildrenLists"))
{
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.isDeleted)
<span>Name: </span> #Html.EditorFor(m => m.Name);
}
delete
1- the newly cannot be removed
You can manually bind click event handler for the new generated <a href="#" class="deleteRow"> element, like below.
success: function (html) {
$("#editorRows").append(html);
$("a.deleteRow").bind("click", function () {
//...
//code logic here
});
}
2- Tried to tag the deleted items as isDeleted = true using Javascript
To achieve the requirement, you can refer to the following code snippet.
<script>
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
$("#editorRows").append(html);
$("a.deleteRow").bind("click", function () {
del_row($(this));
});
}
});
return false;
});
$("a.deleteRow").click(function () {
del_row($(this));
return false;
});
function del_row(el) {
console.log("del");
console.log($(el).siblings("input[id$='__Id']").val());
var childitem_id = $(el).siblings("input[id$='__Id']").val();
if (childitem_id == 0 || childitem_id == "") {
$(el).parent("div.editorRow").remove();
} else {
$(el).siblings("input[id$='__isDeleted']").val("true");
$(el).parent("div.editorRow").hide();
}
return false;
}
</script>
Test Result

Set Form authentication in WEB API

Actually i have two project. One for Mvc and another one is Web Api. I have written form as below in mvc project.
<form>
<div class="form-group">
<input type="email" class="form-control" id="email" placeholder="Username">
</div>
<div class="form-group">
<input type="password" class="form-control" id="pwd" placeholder="Password">
</div>
<div class="checkbox">
<input class="customCheckBox" onclick="setIsRemember()" type="checkbox" name="" value="false"><label for=""><span><span></span></span>Remember me</label>
</div>
<button id="buttonSubmit" class="btn btn-default">LOG IN</button>
</form>
Then i have written script for cross domain as below,
$("#buttonSubmit").click(function (e) {
var user =
{
UserName: $("#email").val(),
Password: $("#pwd").val(),
IsRemember: $(".customCheckBox").val()
}
$.ajax({
type: "POST",
url: "http://localhost:55016/api/ajaxapi/loginmethod",
data: user,
success: function (response) {
if (response.Success == false) {
alert("login fail");
}
if (response.Success == true) {
alert("login true");
}
}
});
});
I have written login credential checking in web Api. After login success i have set form authentication as below in web api source,
public class UserLogOn
{
public interface IFormsAuthentication
{
void SignIn(string userName, bool createPersistentCookie);
void SignOut();
}
public IFormsAuthentication FormsAuth
{
get;
private set;
}
public void FormsChange(IFormsAuthentication formsAuth)
{
this.FormsAuth = formsAuth ?? new FormsAuthenticationService();
}
public void LogOnUserCookieCreation(UserValuesForLogOn user)
{
this.FormsChange(null);
this.FormsAuth.SignIn(user.UserName, user.IsRemember);
if (user.IsRemember)
{
HttpCookie cookie = new HttpCookie("SignedIn");
cookie.Values.Add("UserName", user.UserName);
cookie.Values.Add("Password", user.Password);
FormsAuthentication.SetAuthCookie(user.UserName, true);
System.Web.HttpContext.Current.Response.Cookies.Add(cookie);
}
}
public class FormsAuthenticationService : IFormsAuthentication
{
public void SignIn(string userName, bool createPersistentCookie)
{
FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
}
public void SignOut()
{
FormsAuthentication.SignOut();
}
}
When this above code is working if set authentication in same project. But its not working when set authentication using webapi. Please share your suggestion.
Thanks......

get a view page using jquery in mvc4

Hi I am working with mvc4
I have a razor view page for the action
public ActionResult DeliveryAddress(string userid,int productid)
{
....
return View(m);
}
that contain
<div >DELIVER HERE</div>
when clicking on this i am collecting somedata ifrom this page using jquery,
$(document).ready(function () {
$("#place-order").click(function () {
var userid = $('#selected-userId').html();
var productid = $('#selected-productId').html();
$.get("Products/PlaceOrder/"+ userid, function (data) { });
});
});
and i want to pen another view of action
[HttpGet]
public ActionResult PlaceOrder(int uid)
{
return View();
}
and paste the variable content,
but $.get("Products/PlaceOrder", function (data) { }); is not hitting this action..
please help me.
This is how you need to pass a data to a url in Jquery get method, note the same parameter name is used in the function
$.get('#Url.Action("PlaceOrder","Products")', { uid: userid }, function (data)
{
});
Make sure your URL is correct. Most probably use #Url.Action(). and also pass the parameter using new as shown below.
$.get('#Url.Action("PlaceOrder","Products",new { userid = #userid , productid = #productid })', function (data) {
});
While collecting the data make sure your parameter names are same for both while sending and while receiving.
[HttpGet]
public ActionResult PlaceOrder(int userid, int productid )
{
return View();
}
Just add HTTPGET attribute in your action method as below.
[HttpGet]
public ActionResult PlaceOrder()
{
return View();
}
java script
$("#place-order").click(function () {
var userid = $('#selected-userId').html(); // $('#selected-userId').val();
$.get('#Url.Action("PlaceOrder","Products", new { uid = userid })', function (data) { });
var productid = $('#selected-productId').html();
});
When I want my view code to be fetched like that, or even through the Html.Action() call, I use the PartialView and normally set my Controller Action as:
public ActionResult PlaceOrder(int uid)
{
return PartialView(new TestViewModel() { ID = uid });
}
as an example:
TestViewModel
public class TestViewModel
{
public int ID { get; set; }
}
PlaceOrder.cshtml
#model TestViewModel
<h2>Partial View</h2>
<p>
Partial View paragraph with the id <b>#Model.ID</b>
</p>
Index.html
<hr />
#Html.Action("PartialView", "Home", new { id = 44 })
<hr />
<div class="ap"></div>
<script>
var url = '#Url.Action("PartialView", "Home")';
$.get(url, { id: 54 }, function (data) {
$(".ap").append(data);
});
</script>
result:

Categories