Call a method without loading a view in MVC - c#

I am currently trying to call a method from my view to change a boolean in my database, the only thing i don't know since i am not really familiar with MVC is that whenever i call my controller method it gives me a blank page. I just want to call the method but stay in the actual view.
Here is the part of code in my view.
<td>Delete</td>
And here is the method in my controller
public void PutInBin(int captureId)
{
QueryCaptureToBin queryCaptureToBin = new QueryCaptureToBin();
queryCaptureToBin.Capture_Id = captureId;
client.PlaceCaptureInBin(queryCaptureToBin, userParams);
}

You could use AJAX:
<td>
#Ajax.ActionLink(
"Delete",
"PutInBin",
"Capture",
new {
captureId = Model.Files.Captures.ElementAt(i).Capture_Id
},
new AjaxOptions {
HttpMethod = "POST",
}
)
</td>
and don't forget to include the jquery.unobtrusive-ajax.js script to your page:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
and your controller action:
[HttpPost]
public ActionResult PutInBin(int captureId)
{
QueryCaptureToBin queryCaptureToBin = new QueryCaptureToBin();
queryCaptureToBin.Capture_Id = captureId;
client.PlaceCaptureInBin(queryCaptureToBin, userParams);
return new EmptyResult();
}
and if you wanted to get notification when the delete finishes:
<td>
#Ajax.ActionLink(
"Delete",
"PutInBin",
"Capture",
new {
captureId = Model.Files.Captures.ElementAt(i).Capture_Id
},
new AjaxOptions {
HttpMethod = "POST",
OnSuccess = "onDeleteSuccess"
}
)
</td>
and then you would have your onDeleteSuccess javascript function:
var onDeleteSuccess = function(result) {
// normally the result variable will contain the response
// from the server but in this case since we returned an EmptyResult
// don't expect to find anything useful in it.
alert('The capture was successfully deleted');
};

To refresh the page. Please use below java script function. It's same as above but removed "alert" and used window.location.reload(true). Use in html or cshtml view. Hats off original owner
<script>
var onDeleteSuccess = function(result) {
// normally the result variable will contain the response
// from the server but in this case since we returned an EmptyResult
// don't expect to find anything useful in it.
window.location.reload(true);
// alert('The capture was successfully deleted');
};
</script>

Related

Using Action in Controller every 10min [duplicate]

I have sample code like this:
<div class="cart">
<a onclick="addToCart('#Model.productId');" class="button"><span>Add to Cart</span></a>
</div>
<div class="wishlist">
<a onclick="addToWishList('#Model.productId');">Add to Wish List</a>
</div>
<div class="compare">
<a onclick="addToCompare('#Model.productId');">Add to Compare</a>
</div>
How can I write JavaScript code to call the controller action method?
Use jQuery ajax:
function AddToCart(id)
{
$.ajax({
url: 'urlToController',
data: { id: id }
}).done(function() {
alert('Added');
});
}
http://api.jquery.com/jQuery.ajax/
Simply call your Action Method by using Javascript as shown below:
var id = model.Id; //if you want to pass an Id parameter
window.location.href = '#Url.Action("Action", "Controller")/' + id;
You are calling the addToCart method and passing the product id. Now you may use jQuery ajax to pass that data to your server side action method.d
jQuery post is the short version of jQuery ajax.
function addToCart(id)
{
$.post('#Url.Action("Add","Cart")',{id:id } function(data) {
//do whatever with the result.
});
}
If you want more options like success callbacks and error handling, use jQuery ajax,
function addToCart(id)
{
$.ajax({
url: '#Url.Action("Add","Cart")',
data: { id: id },
success: function(data){
//call is successfully completed and we got result in data
},
error:function (xhr, ajaxOptions, thrownError){
//some errror, some show err msg to user and log the error
alert(xhr.responseText);
}
});
}
When making ajax calls, I strongly recommend using the Html helper method such as Url.Action to generate the path to your action methods.
This will work if your code is in a razor view because Url.Action will be executed by razor at server side and that c# expression will be replaced with the correct relative path. But if you are using your jQuery code in your external js file, You may consider the approach mentioned in this answer.
If you do not need much customization and seek for simpleness, you can do it with built-in way - AjaxExtensions.ActionLink method.
<div class="cart">
#Ajax.ActionLink("Add To Cart", "AddToCart", new { productId = Model.productId }, new AjaxOptions() { HttpMethod = "Post" });
</div>
That MSDN link is must-read for all the possible overloads of this method and parameters of AjaxOptions class. Actually, you can use confirmation, change http method, set OnSuccess and OnFailure clients scripts and so on
If you want to call an action from your JavaScript, one way is to embed your JavaScript code, inside your view (.cshtml file for example), and then, use Razor, to create a URL of that action:
$(function(){
$('#sampleDiv').click(function(){
/*
While this code is JavaScript, but because it's embedded inside
a cshtml file, we can use Razor, and create the URL of the action
Don't forget to add '' around the url because it has to become a
valid string in the final webpage
*/
var url = '#Url.Action("ActionName", "Controller")';
});
});
Javascript Function
function AddToCart(id) {
$.ajax({
url: '#Url.Action("AddToCart", "ControllerName")',
type: 'GET',
dataType: 'json',
cache: false,
data: { 'id': id },
success: function (results) {
alert(results)
},
error: function () {
alert('Error occured');
}
});
}
Controller Method to call
[HttpGet]
public JsonResult AddToCart(string id)
{
string newId = id;
return Json(newId, JsonRequestBehavior.AllowGet);
}
You can simply add this when you are using same controller to redirect
var url = "YourActionName?parameterName=" + parameterValue;
window.location.href = url;
You can set up your element with
value="#model.productId"
and
onclick= addToWishList(this.value);
I am using this way, and worked perfectly:
//call controller funcntion from js
function insertDB(username,phone,email,code,filename) {
var formdata = new FormData(); //FormData object
//Iterating through each files selected in fileInput
formdata.append("username", username);
formdata.append("phone", phone);
formdata.append("email", email);
formdata.append("code", code);
formdata.append("filename", filename);
//Creating an XMLHttpRequest and sending
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Home/InsertToDB');//controller/action
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
//if success
}
}
}
in Controller:
public void InsertToDB(string username, string phone, string email, string code, string filename)
{
//this.resumeRepository.Entity.Create(
// new Resume
// {
// }
// );
var resume_results = Request.Form.Keys;
resume_results.Add("");
}
you can find the keys (Request.Form.Keys), or use it directly from parameters.
You can easily make a <a> link in your view.
<a hidden asp-controller="Home" asp-action="Privacy" id="link"></a>
then in you javascript code use this:
location.href = document.getElementById('link').href;

Passing a value of a textbox from View to a method/action in Controller and then data from response back to form

I have a form in a create view (not sure if relevant but is done with ChameleonForms).
Bellow of an edit box named let say "CompanyNumber" I have an html button and I want that OnClick to send the value already written of edit box as parameter to an method in my Controller but without submitting the form, because before saving the form I have to manually add fields value that are not retrieved with json response.
Mainly the method make a webrequest and returns a json that I use in method to populate the model relevant to the given view with all available information that I can get.
So at this moment I have this in the view:
#*Form region*#
#s.FieldFor(m => m.CompanyNumber)
<button id="Ask" type="button" class="btn btn-default">Ask the web!</button>
#*Script region*#
<script type="text/javascript">
$('#Ask').click(function(){
var companynumber = $('#CompanyNumber').val();
$.ajax({
type: 'POST',
data:{CompanyNumber:companynumber},
//url from the controller's action method
url: '#Url.Action("Customers","GetCompanyInfo")/?CompanyNumber='+$('#CompanyNumber').val(),
//with the following 2 lines, raise HTTP500
//dataType: 'json',
//contentType: "application/json; charset=utf-8",
success: function (data) {
//Here you would update the textboxes, the 'data' variable contains the html from the partialview
//alert("here we have: " + data.d.toString());
},
error: function () {
//Manage errors
}
});
}
)
</script>
and in Controller:
private InvoiceDBEntities db = new InvoiceDBEntities();
public Customers cModel = new Customers();
//Ask the web for company details
public ActionResult GetCompanyInfo(string CompanyNumber)
{
//call for openapi.ro
string CompanyCUI = CompanyNumber;
// Create a new 'Uri' object with the specified string.
Uri myUri = new Uri("https://api.openapi.ro/api/companies/" + CompanyCUI + ".json");
// Create a new request to the above mentioned URL.
WebRequest myWebRequest = WebRequest.Create(myUri);
//Add the required header to request
myWebRequest.Headers.Add("x-api-key", "some_key_relevant_to_me_and_my_scenario");
// Assign the response object of 'WebRequest' to a 'WebResponse' variable.
WebResponse myWebResponse = myWebRequest.GetResponse();
// Read the response into a stream
var dataStream = myWebResponse.GetResponseStream();
var reader = new StreamReader(dataStream);
var jsonResultString = reader.ReadToEnd();
// Deserialize
var CompanyInfoData = Newtonsoft.Json.JsonConvert.DeserializeObject<CustomerModels>(jsonResultString);
//Bind to model for feed him
cModel.Phone1 = CompanyInfoData.telefon;
cModel.CompanyRegistration = CompanyInfoData.numar_reg_com;
cModel.Name = CompanyInfoData.denumire;
cModel.CompanyNumber = CompanyInfoData.cif;
cModel.Address = CompanyInfoData.adresa;
//other properties of the related model....
ViewData["Customer"] = cModel;
return View(cModel);
}
//other actions
// GET: Customers/Create
public ActionResult Create()
{
return View();
}
// POST: Customers/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "CustomerID,Name,CompanyNumber,CompanyRegistration,CompanyBank,CompanyIBAN,Address,CP,City,ContactPerson,Phone1,Phone2,Fax,Email,Notes")] Customers customers)
{
if (ModelState.IsValid)
{
db.Customers.Add(customers);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customers);
}
At the end I obtain the required json response and I fill my model with data.
So my question is how to instruct the method to send back the obtained values to be rendered as text values to relevant editboxes in the same form?
After this I will be able to do validation checks and other stuff before sending the form to saving
I have to say that at first step I experimented this, with CompanyNumber hardcoded into my method, (in fact all method code was inside the default Index action of controller) and for Index view associated with the Controller it works fine, the form was filled with all available data values that I was able to retrieve.
Regards
You should use an ajax call pointing to the action in the controller, and retrive the information as a partial view (or json, depending on the circunstances). The following example uses JQuery
$(#Ask).click(function(){
var companynumber = $('#CompanyNumber').val();
$.ajax({
type: 'POST',
data:{
CompanyNumber:companynumber
},
//url from the controller's action method
url: url,
success: function (data) {
//Here you would update the textboxes, the 'data'
//variable contains the html from the partialview
},
error: function () {
//Manage errors
}
})
}
Finally I make it working
I will add only relevant for who may need a similar stuff:
The script at the end of the view:
<script type="text/javascript">
$('#Ask').click(function () {
var companynumber = $('#CompanyNumber').val();
$.ajax({
type: 'POST',
data: {
CompanyNumber: companynumber
},
//url from the controller's action method e.g. GetCompanyInfo
url: '/Customers/GetCompanyInfo/',
dataType: "json",
success: function (data) {
//Here you would update the textboxes, the 'data' variable contains the html/text from the fill
$('#CompanyNumber').val(data.cif);
$('#CompanyRegistration').val(data.numar_reg_com);
$('#Name').val(data.denumire);
$('#Phone1').val(data.telefon);
$('#Fax').val(data.fax);
$('#Address').val(data.adresa);
$('#ZIP').val(data.cod_postal);
//alert("here: " + data.toString());
},
error: function () {
//Manage errors
}
});
//console.log();
}
)
</script>
The controller (simplified):
public ActionResult GetCompanyInfo(string CompanyNumber)
{
//call for openapi.ro
string CompanyCUI = CompanyNumber;
// Create a new 'Uri' object with the specified string.
Uri myUri = new Uri("https://api.openapi.ro/api/companies/" + CompanyCUI + ".json");
// Create a new request to the above mentioned URL.
WebRequest myWebRequest = WebRequest.Create(myUri);
//Add the required header to request
myWebRequest.Headers.Add("x-api-key", "some_key_relevant_to_me_and_my_scenario");
// Assign the response object of 'WebRequest' to a 'WebResponse' variable.
WebResponse myWebResponse = myWebRequest.GetResponse();
// Read the response into a stream
var dataStream = myWebResponse.GetResponseStream();
var reader = new StreamReader(dataStream);
var jsonResultString = reader.ReadToEnd();
// Deserialize
var CompanyInfoData = Newtonsoft.Json.JsonConvert.DeserializeObject<CustomerModels>(jsonResultString);
return Json(CompanyInfoData,JsonRequestBehavior.AllowGet);
}
and the form part of the view (in my case done with ChameleonForms, but don't important):
#using ChameleonForms
#using ChameleonForms.Component
#using ChameleonForms.Enums
#using ChameleonForms.Templates
#using ChameleonForms.ModelBinders
#model DirectInvoice.Models.Customers
#{
ViewBag.Title = "Create";
}
<div>
#using (var f = Html.BeginChameleonForm())
{
#Html.AntiForgeryToken()
using (var s = f.BeginSection("Add a new customer"))
{
#s.FieldFor(m => m.CompanyNumber)
#*<button type="button" onclick="location.href='#Url.Action("GetCompanyInfo", "Customers", new { id = "Ask" })'" class="btn btn-default">Ask the web!</button>*#
<button id="Ask" type="button" class="btn btn-default">Ask the web!</button>
#s.FieldFor(m => m.Name)
#s.FieldFor(m => m.CompanyRegistration)
#s.FieldFor(m => m.Phone1).Placeholder("0XX X XXX XXX")
#s.FieldFor(m => m.Fax).Placeholder("0XX X XXX XXX")
#s.FieldFor(m => m.Email).Placeholder("name#email.com")
#s.FieldFor(m => m.Address)
#s.FieldFor(m => m.ZIP)
#s.FieldFor(m => m.City)
}
using (var n = f.BeginNavigation())
{
#n.Submit("Save the new customer...")
}
}
</div>
Thank you to all for ideas!

How to return a dynamic number of multiple partial views inside another partial view

I want to return a dynamic number of multiple partial views inside another partial view in the controller, and inject it to the DOM using an Ajax call.
The user is going to select a package (radio buttons) and depending on this package I need to return X number of forms to be filled by the user.
This is my Ajax code:
$(function() {
var serviceURL = "/NewOrderRequestForms/GetFormsToCreateNewOrderRequest";
$(":radio").change(function() {
$.ajax({
url: serviceURL,
type: "POST",
data: { account: $("#AccountId").val(), serviceAvailabilityPackageId: $(":radio:checked").val() },
success: function(xhrData) {
populateNORForms(xhrData);
},
error: function() {
alert("error");
}
});
});
});
My controller method looks like the following:
public virtual ActionResult GetFormsToCreateNewOrderRequest(Guid account, int serviceAvailabilityPackageId)
{
var customerNumber = _authorizationUtil.GetAccount(account).CustomerNumber;
var result = _customFormService.GetFormsToCreateNewOrderRequest(customerNumber.Value,
serviceAvailabilityPackageId).Select(x => x.FormKey);
var forms = CustomFormUtil.GetCustomMetaPartial(result);
//I am confused here
//return PartialView(something)
}
CustomFormUtil.GetCustomMetaPartial(result) is going to return an IEnumerable<string> of 1 to 6 strings for example "form1, form3" or "form1, form2, form3, form6" etc. I am using this to return a Dictionary of View names and Models to add them in my ultimate partial view.
//Dictionary for Custom Meta Partialviews
public static Dictionary<string, CustomMetaPartialViewModel> CustomMetaPartial2 = new Dictionary<string, CustomMetaPartialViewModel>()
{
{"form1_v1", new CustomMetaPartialViewModel(MVC.Service.NewOrderRequestForms.Views.form1_v1, new form1_v1())},
{"form2_v1", new CustomMetaPartialViewModel(MVC.Service.NewOrderRequestForms.Views._form2_v1,new form2_v1())},
...
{"form7_v1", new CustomMetaPartialViewModel(MVC.Service.NewOrderRequestForms.Views._form7_v1,new form7_v1())}
};
My question is: how can I add these partial Views with Models into another big partial view and send this one back to the View?
Ok, I have my answer for this, instead of using Ajax to call the List of string I am using to create a PartialView that renders everything I need.
This is my AJAX call
$(function () {
var serviceURL = "/NewOrderRequestForms/GetFormsToCreateNewOrderRequest";
$(":radio").change(function () {
$.ajax({
url: serviceURL,
type: "POST",
data: { account: $("#AccountId").val(), serviceAvailabilityPackageId: $(":radio:checked").val() },
success: function (xhrData) {
$('#NORForms').html(xhrData);
},
error: function () {
alert("error");
}
});
});
});
And the function in the controller is the following:
public virtual ActionResult GetFormsToCreateNewOrderRequest(Guid account, int serviceAvailabilityPackageId)
{
var customerNumber = _authorizationUtil.GetAccount(account).CustomerNumber;
var result = _customFormService.GetFormsToCreateNewOrderRequest(customerNumber.Value,
serviceAvailabilityPackageId).Select(x => x.FormKey);
return PartialView(Views.GenericParentView, result);
}
I am getting all the information I need from the View, however, instead of returning a List of Strings to the callback in Ajax, I am returning a PartialView having the list of Strings that I needed as the parameter that I need to render the partials Views. Here is the new Partial View that handles this.
#using UI.Shared.Utils
#model IEnumerable<string>
#{
var forms = CustomFormUtil.GetCustomMetaPartial2(Model);
var result = forms.Select(x => x.Model);
}
#using (Html.BeginForm(MVC.Service.NewOrderRequest.Index(new TdlMasterModel()), FormMethod.Post))
{
foreach (var form in forms)
{
{ Html.RenderPartial(form.View, form.Model); }
}
<p style="clear: both">
<input id="submitNOR" type="submit" value="Submit" style="float: right" />
</p>
}
I am sending a list of Strings, and using it to spit out a Dictionary with Model,Views and I am rendering them in the partial view, using a foreach loop.
Saving me at the end some extra Ajax calls, in resume I was tackling my problem the wrong way.

How to replace div's content by partial view or update it's content depending on what json result returns on ajax complete?

Well I have simple ajax form:
This is MyPartialView
#using(Ajax.BeginForm("action", "controller", new AjaxOptions
{
OnBegin = "beginRequest",
OnComplete = "completeRequest",
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "div-to-replace"
}, }))
{
<input type="text" id="my-input" />
...
}
This is parent view:
<div id="div-to-replace">
#Html.RenderPartial("MyPartialView")
</div>
In my controller I have:
[HttpPost]
public ActionResult action(Model model)
{
if (ModelState.IsValid)
{
// do staff with model
// return partial view
return PartialView("MyPartialView");
}
// else add error and return json result
return Json(new {error = "invalid data"});
}
And my javascript on ajax complete method:
function completeRequest(data) {
var result = $.parseJSON(data.responseText);
if (result != 'undefined' && result != null && result.error) {
// just display error and not replace all content
// attachModelError is my custom method, it just adds vlaidation-error class to inputs, etc.
attachModelError("my-input", result.error);
return;
}
// or show returned html (depending on returned model form inputs will be modified:
// select box with different items in my case
$('#div-to-replace').html(data.responseText);
}
But the problem is I have empty #div-to-replace if model state is invalid. If model state is ok every thing works fine. If I use different insertion mode it creates duplicates of div's content before or after div.
Summary:
I want different InsertionMode behavior depending on json result. I don't need replace data if (result != 'undefined' && result != null && result.error).
I had to solve this problem once so very long ago. I came up with a simple solution, which today, may not be the best solution but it gets the job done.
My solution involved setting up a controller action that would render just the partial with data that it would need and have my JavaScript request it.
C#
MyController: Controller
{
public ActionResult GetPartialViewAction()
{
return PartialView("mypartialview", new partialViewModel());
}
}
JavaScript
$.ajax({
url: "/my/getpartialaction/"
}).done(function(data) {
$("#partialViewDiv").html(data);
});
HTML
<div id="partialViewDiv"></div>
A better solution would be to use a MVVM/MVC JavaScript library that would allow you to leverage html templates and only have to transmit the data over your ajax solution. I recommend looking into knockout.js or backbone.js for this more accepted pattern.
I have the same problem with the default c# ajax forms. I have a solution what might work.
jQuery:
$(function () {
var ajaxFormSubmit = function () {
var $form = $(this);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
data: $form.serialize(),
cache: false
}
$.ajax(options).done(function (data) {
data.replaces.each(function (replace) {
$(replace.id).replaceWith(replace.html);
});
});
return false;
};
$("form[data-ajax='true']").submit(ajaxFormSubmit);});
form.cshtml
#using (Html.BeginForm("Create", "Menu", FormMethod.Post, new { data_ajax = "true" }))
{}
model sample
public string Id {get;set;}
public string Html {get;set;}
The last thing you need to do in your controller is return a json result with a list of your model sample, id is target element to update, for the html you must use a render partial / or view as string.
For render view to partial see [question]: https://stackoverflow.com/questions/434453

How to make UpdateTargetId work in Ajax.ActionLink?

I have this method in the controller
[HttpDelete]
public void DeleteDocument(int id)
{
//Here I do the deletion in the db
}
In the view I have this, calling a method that returns a partial view
#{ Html.RenderAction("GetDocumentsByMember"); }
The GetDocumentsByMember method
public ActionResult GetDocumentsByMember()
{
var companyGuid = HttpContextHelper.GetUserCompanyGuid();
var documents = _service.GetUploadedDocumentsByMember(companyGuid);
return PartialView(documents);
}
And the partial view
#model IEnumerable<GradientCapital.DomainModel.Entity.Document.Document>
<div id="uploadeddocuments">
#*Here there's a table and at one of the columns there's the next link*#
<td id="delete">
#Ajax.ActionLink("Delete", "DeleteDocument", new { id = document.Id },
new AjaxOptions
{
Confirm = "Are you sure you want to delete?",
HttpMethod = "DELETE",
OnComplete = "deleteComplete"
})
</td>
</div>
And deleteComplete just refresh everything
<script type="text/javascript">
function deleteComplete() {
window.location.reload();
}
</script>
Quite long (is correctly formatted?) code for a simple question, I can't make the ajaxoption UpdateTargetId work here instead of having to call this deleteComplete function. Any idea?
Thanks
Instead of reloading the entire page you could call the GetDocumentsByMember action using AJAX and update only the portion of the DOM that has actually changed:
<script type="text/javascript">
function deleteComplete() {
$.ajax({
url: '#Url.Action("GetDocumentsByMember")',
type: 'GET',
cache: false,
success: function(result) {
$('#uploadeddocuments').html(result);
}
});
}
</script>
Also you'd better use OnSuccess = "deleteSuccess" instead of OnComplete = "deleteComplete" because you should update only if the Delete call actually succeeded. Don't forget that the OnComplete callback is always invoked, no matter whether the AJAX call succeeded or not.

Categories