Ajax.ActionLink POST doesn't work in ASP.NET MVC 5 - ajax

A quick summary of the situation:
In my View I have this piece of Razor code:
#{
ViewBag.Title = "Index";
AjaxOptions options = new AjaxOptions();
options.HttpMethod = "POST";
}
...
#Ajax.ActionLink("Linkname", "CreateChallenge", new { challengedId = Model.UserId },options);
Than in my controller:
[Authorize]
[HttpPost]
public string CreateChallenge(string challengedId)
{
ChallengeRepository.CreateChallenge(challengedId);
return "Sendend!";
}
I get an 'Resource not found' error when I click the link but when I remove the [HttpPost] attribute everything works fine. But I want a POST method. I have looked around and found some similar problems but none of the solutions worked for me.

UPDATE
Spoke too soon, remembered that you need the jQuery.Ajax.Unobtrusive http://www.nuget.org/packages/jQuery.Ajax.Unobtrusive/ package
If you install this and reference it in you view it should work, it did i my OOTB test :)
Did a quick test myself, it seems you cant use Ajax.ActionLink to issue a POST request, it does a GET even though you set POST in AjaxOptions. You can see this if you use fiddlr to monitor the traffic.
You can also use the Postman extension for Chrome to test it, you will see that the action method actually behaves as it should when you POST to it. But you get the 404 because it actually does a GET
If it were me I would use jQuery to do the post. You can see more here http://api.jquery.com/jquery.ajax/

Related

Cannot POST api call from .net core MVC

I have the following code in my .net core MVC application:
[HttpPost]
public void GetCustomerInfo([FromBody] string value)
{
string data = value;
}
after deploy this to my azure we app and call 'azuresiteurl/api/controller/GetCustomerInfo' page not found error occurs.
Can anyone please help?
you are using a get request but you had defined it as a post request change it as [httpget]
You should pass the string value in the request body and since it is marked as a HttpPost method, it has to be a Post call from the client.
Additionally, check if you are indeed sending the value in the request body. The content type should be coming in correctly for FromBody to work and map the primitive type.
I suggest you go through the answer of this question.
WebApi POST works without [FromBody]?

Customize Authorize Redirect

I am using Beta 4 and when I use the [Authorize] attribute, it redirects to /account/login like i'd expect but that's no the name of my URL. I could customize this in web.config but I don't know where to configure it in ASP.NET 5. Any ideas?
Not sure if this will help but I did download VS 2015 RC.
I’ve created a new MVC 6 website project and launched (F5) it. While being unauthenticated, I tried reaching the ManageController which is decorated with the [Authorize] attribute.
Needless to say, I was redirected to the Account/login view but nowhere have I found where this is configured.
I did manage to add the following inside the ConfigureServices() method of the Startup.cs:
services.Configure<CookieAuthenticationOptions>(options =>
{
options.LoginPath = new PathString("/Gazou/Index");
});
Just above the:
services.AddMvc();
I’ve then created my new GazouController with a simple Index IActionResult().
Ran the application again, tried accessing the ManageController but this time, I was redirected to the Index method of my GazouController instead of the default behavior.
Hope this helps.
Vince
I think you didn't format it with code so I can't see it, but this is what I found:
services.Configure<CookieAuthenticationOptions>(opt =>
{
opt.LoginPath = PathString.FromUriComponent("/Auth/Login");
});

How to use Breeze IQueryable with CORS?

I use a method to add CORS handlers to my response that is called by a client using Breeze.
You can read more about how I got that working here: Controller not filtering data in Breeze query in DotNetNuke Module
However, I noticed that while $filter works, $expand and $select do not.
So my question is: How can I use return a HttpResponseMessage Type and still use Breeze (I need to do this for CORS).
To prove this, I downloaded and changed the Todos sample:
Original method (works)
http://example/api/todos/todos?$select=isdone
[HttpGet]
public IQueryable<TodoItem> Todos()
{
return _contextProvider.Context.Todos;
}
My method with CORS wrapper (does not expand or select)
http://example/api/todos/TodosCors?$select=isdone
[HttpGet]
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
public HttpResponseMessage TodosCors()
{
var response = Request.CreateResponse(HttpStatusCode.OK, (IQueryable<TodoItem>)_contextProvider.Context.Todos);
return ControllerUtilities.GetResponseWithCorsHeader(response);
}
public static HttpResponseMessage GetResponseWithCorsHeader(HttpResponseMessage response)
{
response.Headers.Add("Access-Control-Allow-Origin", "*");
return response;
}
I'm going to comment mainly on the CORS aspect of your question. The part about $expand and $select is addressed in the StackOverflow question to which you refer. In brief, [Queryable] is the Web API attribute which does not support $expand and $select. I think you want the [BreezeQueryable] attribute that does.
I can not say for sure but I do not believe the code you show is the proper way to implement CORS for the Web API. At least I've not seen it done this way.
There are two ways known to me; both involve adding message handlers.
The first is the way we did it in the Breeze Todo sample; the second is the with the Web API CORS support that is on the way.
The way we did it is simplistic but effective. We don't talk about it because we intend to defer to the the approved Web API way when it arrives (soon I hope).
In the Todo demo, look for App_Start/BreezeSimpleCorsHandler.cs. You can just copy it into your own App_Start folder with no changes except to the namespace.
Then your server has to call it. In the Todo sample we did so in the BreezeWebApiConfig.cs but you could put it in Global.asax or in anything that is part of the server boot logic.
// CORS enabled on this server
GlobalConfiguration.Configuration.MessageHandlers.Add(new BreezeSimpleCorsHandler());
As it happens, someone has tried Breeze with the forthcoming Web API CORS NuGet package ... and discovered a bug in Breeze. We have to work that through ... and we will. We really want that way to be THE way.
Until then, you can follow the Todo sample precedent.

ActionMailer fail with "Value cannot be null. Parameter name: uriString"

I'm trying to use ActionMailer 0.7.0 to send a email from my MVC 3 project.
I've followed the sample posted in the project site to the letter.
But when I try to send the email the following error always occurs:
"Value cannot be null. Parameter name: uriString"
It occurs the the #Url.AbsoluteAction in the email body.
#using ActionMailer.Net
#model User
#{
Layout = null;
}
Welcome to My Cool Site, #Model.FirstName
We need you to verify your email. Click this nifty link to get verified!
// The error happens in the line bellow
#Url.AbsoluteAction("Verify", "Account", new { code = #Model.EmailActivationToken.ToString() })
Thanks!
Can some one help me? What am I missing?
After struggling a few days trying to solve the problem using the code proposed in the sample I gave up.
I've download the source and found out that the problem occurs when your RouteCollection is not standard (which is my case).
So I found an elegant work around that worked for me.
Instead sending the Token to the view and use the Url.AbsoluteAction method I used the Url.Action with the protocol parameter in the controller and sended the complete url in the view model. Like this:
new EmailsController().ActivationMail(new ActivationMailViewModel { Email = data.Email, FirstName = data.Name, ActivationLink = Url.Action("VerifyEmail", "Mail", new { code = data.ActivationToken.ToString() }, "http") }).Deliver();
The view became:
#using ActionMailer.Net
#model User
#{ Layout = null; }
Welcome to My Cool Site, #Model.FirstName
We need you to verify your email. Click this nifty link to get verified!
#Model.ActivationLink
Thanks!
About the SMTP host problem, I found out that in Web.Config even if you set the deliver for "SpecifiedPickupDirectory" you need to add an empty host tag. It's not specified in any ActionMailer sample. Here is the final configuration:
<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<network host="none" />
<specifiedPickupDirectory pickupDirectoryLocation="C:\temp\" />
</smtp>
</mailSettings>
</system.net>
I hope it helps someone.
Best luck for everybody.
I've just spent a couple of hours implementing ActionMailer into my MVC project.
I found Scott's screencast really helped me.
http://www.youtube.com/watch?v=QQRzYo7k9Vs&hd=1
It explains how to get round the SMTP host issue, as well as how to set up the User models etc.
I'm still getting stuck on user email verification and will try to let you know if I sort it out.
However, you don't need this to send 'ordinary' emails. So my advice would be to leave it out for now until you can get the emails working OK.
Hope that helps, and I'll be back to you when I sort out email verification!
Cheers
Chewie

Best way to deal with renaming a controller

Working with ASP.NET MVC3, site is in beta and customer decided to rename one of the controllers.
http://domain.com/foo[/*] -> http://domain.com/bar[/*]
What is the most straightforward way to handle redirecting so I don't break any foo bookmarks?
Keep the old controller around so the old URLs still work.
Or add a rewrite rule. Something like:
domain.com/foo(/[_0-9a-z-]+)
to:
domain.com/bar{R:1}
URL Rewrite in IIS
http://technet.microsoft.com/en-us/library/ee215194(WS.10).aspx
http://www.iis.net/download/URLRewrite
If you are using MVC.NET you probably already have URL Rewrite installed.
Another option would be to register a specific route for the old controller name in the Global.asax.cs.
routes.MapRoute(
"RenamedController", // Route name
"[OldControllerName]/{action}/{id}", // URL with parameters
new { controller = "[NewControllerName]", action = "Index", id = "" } // Parameter defaults
);
Add that before the standard default route, and your new controller should respond to both old and new names.
A 302 redirect would be fine, if you can figure out how to do that in IIS. This screenshot suggests it's not that arduous. Alternately, if you're using Castle Windsor you may want to register an interceptor that uses HttpResponse.Redirect()
REST standard suggests the best way to handle this issue is by returning a 301(Moved permanently request). Stack Overflow Post REST Standard
In .Net I recommend using Controller.RedirectToActionPermanent in your controller. See: ASP.NET, .NET Core
Code Example(should work for both ASP and Core):
public class MyController : ControllerBase
{
public IActionResult MyEndpoint(string routeValues1, string routeValues2)
{
return RedirectToActionPermanent("action", "controller", new { value1 = routeValues1, value2 = routeValues2 });
}
}
using MapRoute doesn't make sense in this case. MapRoute is really meant to provide a custom routing solution throughout the system. Its not really meant to deal with individual Redirects. As far as I'm aware it doesn't actually inform the user they are being redirected. See: Creating Custom Routes (C#)

Resources