I am trying to call a method inside a controller in MVC from a javascript action. The javascript action is supposed to invoke this method inside the controller and send some parameters to it.
My Javascript code looks like this:
location.href = '#Url.Content("~/Areas/MyArea/MyMethod/"+Model.MyId)';
My Method is defined as follows:
[HttpGet]
public ActionResult MyMethod(int? MyId)
{
doSomething(MyId);
return View("MyView");
}
However, when i debug the application, when the method is called the MyId parameter is passed as null and not as the current value of the MyId parameter in my model. What can I do to correctly send or retrieve this value? Thanks!
In your route definition I suppose that the parameter is called {id} and not {MyId}:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
So try to be more consistent and adapt your controller action parameter name accordingly:
[HttpGet]
public ActionResult MyMethod(int? id)
{
doSomething(id);
return View("MyView");
}
Also you probably wanna use url helpers instead of hardcoding some url patterns in your javascript code:
window.location.href = '#Url.Action("MyMethod", "SomeControllerName", new { area = "MyArea", id = Model.MyId })';
The Url.Content helper is used to reference static resources in your site such as javascript, css and image files. For controller actions it's much better to use the Url.Action helper method.
Related
I am not getting how to pass data to the controller to update data, below I have given code.
// below is my jquery which I am using to pass form data to the controller.
function editProfile(profileData){
$("#profile_name").val(profileData.name)
$("#profile_id").val(profileData.id);
$("#profile-modal-lg").modal('show');
$("#profile-form").attr('action',"text/edit/"+profileData.id);
}
// below is my route
Route::post('text/edit/{profile}', 'profileController#editProfileData')->name('profile.edit');
// inside controller I am having a function called edit profile
public function editProfileData(Profile $profile,profileRequest $request){
$profile->update($request->all());
return redirect()->back();
}
Is your form method set to 'POST'? If not, try setting the form method attribute to 'POST'. You might also want to add slash at the start of your url to target the absolute url.
$("#profile-form")
.attr('method', 'POST')
.attr('action', `/text/edit/${profileData.id}`);
I have this function located in a controller called AccountCodes.
[ValidateAntiForgeryToken]
[HttpPost]
public async Task<ActionResult> Process()
{
JsonResult result = new JsonResult(null);
List<string> uploadResults = new List<string>();
return Ok(uploadResults);
}
My intention is to use dropzone to push files to this function. When I try to load the url in the razor view in a variable like this:
var url = "#Url.Action("Process", "AccountCodes",new { area="Configurations"})";
However, when I load the page and look at the console, the url is always "". Am I missing something?
EDIT:
This is where I put the javascript code:
$(document).ready(function () {
var url = "#Url.Action("Process", "AccountCodes",new { area="Configurations"})";
$("#reset").attr("disabled", true);
});
Your code is correct. It may because that you have some wrong global configuration.
Please verify the following things:
Step 1: Check your application
Use MVC in your start up:
// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Other middlewares.
app.UseMvcWithDefaultRoute();
}
Step 2: Check your controller
Make sure there is a controller named AccountCodesController.
Make sure AccountCodesController extends Controller.
Check your routes. If you specify [Route("Something")] to your controller, make sure it is absolutely correct.
Step 3: Try adding a route to your action.
Adding an attribute [Route('SomeAction')] to your action Process might solves this.
Step 4: Check your area existance
Please make sure your controller is located in correct area as this document mentioned: https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/areas?view=aspnetcore-2.2#areas-for-controllers-with-views .
namespace MVCareas.Areas.Products.Controllers
{
[Area("Products")]
public class ManageController : Controller
So I have model entity Place that has to have initialized some relations.
Now I am using autocreated model form-backing bean in controller as follows:
#GetMapping(value = "/add")
public String addPlacePage(final Place place, Model model) {
model.addAttribute("services", serviceRepository.findAll())
.addAttribute("categories", categoryRepository.findAll())
.addAttribute("cities", cityRepository.findAll());
return "admin/place/addPlace";
}
Place place is created my Spring (Spring-MVC probably). Is there a way to provide a factory method for backing bean? I would like to not to do this in controller.
I have tried to put factory code in my configuration like this:
#Bean
#Scope(value = "prototype")
public Place place() {
log.info("Creating place in FACTORY");
Place place = EntityFactory.emptyPlace();
return place;
}
but this does not work.
So I have ask the same question in #spring channel on freenode, and this is something that came up thanks to user <#_ollie>. In order to do what I want, #ModelAttribute method should be defined in controller like this:
#ModelAttribute
private Place emptyPlace(){
log.info("Creating place in FACTORY");
Place place = EntityFactory.emptyPlace();
return place;
}
and related docs are here
https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-ann-modelattrib-methods
In my controller, my create method takes a viewModel that inherits from DynamicObject. The reason is that I need static properties on the model, but I may also add things to it via JavaScript before I pass it to the controller.
So, I have:
public class MyViewModel: DynamicObject {
public string id {get;set;}
}
[HttpPost]
public IHttpActionResult Create(MyViewModel viewModel) {
// save to Db
}
From the JavaScript (using Angular), I've passed in this viewmodel:
var vm = { id: 1, name: "Jim"};
However, this does not work and is throwing me this error:
[{"PropertyName":null,"ErrorMessage":null,"ErrorCode":null,"AttemptedValue":null,"CustomState":null}]
I haven't found an example of what I'm trying to do, but I would think making an object dynamic would allow for this. What am I missing here?
Problem Statement:View not able to load on ajax success method.
Description:
I'm having couple of dropdowns as cascaded(second binding based on the value of first).
On change of the first dropdown I'm binding second dropdown and again on change of the second dropdown,now on right side I want to display a list of record based on the two dropdown values.
For this,I'm using the following JS code in onchange event for the dropdown 2:
function ShowDocsList() {
var teamId = $('#TeamID').val();
var projectId = $("#ProjectID").val();
var Url = "#Url.Content("~/DocsHome/DocsList")";
$.ajax({
url: Url,
type:'POST',
dataType: 'html',
data: { TeamID: teamId ,ProjectID : projectId},
success: function (data) {
return data;
$('.docs-detail').html(data);
}
});
Here,in DocsHome Controller,DocsList method is getting hit on change of second dropdown which is project dropdown.But the view is not getting rendered .Following is my Controller Code:
public ActionResult DocsList(int teamId, int projectId)
{
List<CustomerViewModel> customerViewsModels = SmartAdminHelper.GetCustomers(db1);
if (Request.IsAjaxRequest())
return PartialView("DocsList");
else
return View("DocsList");
}
Again ,I'm getting record in List but while debugging it does not pass to the DocsList view which according to me is correct.
Here DocsList is the view I want to render as a partial view on change of the second dropdown.
According to my knowledge,while debugging it comes to the point return PartialView("DocsList") but then again it goes back to the ajax success method and finally I find that there I'm doing something wrong.
Earlier I have Json to get data but here I'm calling actionmethod from ajax. So, not sure that also might be a problem as I'm new to this.
What and where exactly I'm doing wrong?
Saroj, I see that this is an old question and that you needed to get it done quickly, but if you happend to come back to this, I'll add my two cents. You need to remove the return statement that David and Ehsan mention above. The rest of the callback function does what it should. In your action method it doesn't look like you're doing anything with the parameters you pass in. I'm assuming that you are going to figure that out after you get the view down to the client. So, lets get that view down to the client.
I like to pass the rendered partial view back to the client as a string of HTML. I do this using a method that I keep in a controller base class that each of my controllers inherit from. To use the method you will need to reference System.Web.Mvc and System.IO namespaces.
The method looks like this:
private string RenderViewToString( string viewName, object model ) {
ViewData.Model = model;
using ( var sw = new StringWriter() ) {
var viewResult = ViewEngines.Engines.FindPartialView( ControllerContext, viewName );
var viewContext = new ViewContext( ControllerContext, viewResult.View, ViewData, TempData, sw );
viewResult.View.Render( viewContext, sw );
viewResult.ViewEngine.ReleaseView( ControllerContext, viewResult.View );
return sw.GetStringBuilder().ToString();
}
}
You pass your model and the name of the view to the method and it returns the rendered view HTML as a string which you can return to the client as a ContentResult.
Update your action method like so:
public ActionResult DocsList(int teamId, int projectId)
{
List<CustomerViewModel> customerViewsModels = SmartAdminHelper.GetCustomers(db1);
if (Request.IsAjaxRequest())
var viewContents = RenderViewToString("DocsList", customerViewsModels);
return Content(viewContents);
else
return View("DocsList");
}
Assuming that the element that you want the rendered view to appear in has the css class '.docs-detail' on it you'll be in business. Hope this helps!