How do you create a confirmation message in .net Core 2.1 RazorPages? - asp.net-core

Hopefully not a dumb question- I am rewriting an app from .net core mvc to .net core Razor. In MVC I use viewbags to create and display confirmation of actions being successful or display error message if not. Viewbags don't seem to be used or available in the same way for Razor pages in .net core 2.1.
How do you achieve the above in Razor pages? Any code snippets as example would be helpful. Thanks

We can use a Post-Redirect-Get pattern to display a message after an action.
Here is an example that uses TempData to store a message during a POST and then redirects to a GET. Using TempData to store the message is particularly appropriate for redirection, because the data only exists until something reads it.
SomePage.cshtml
#page
#model SomePageModel
#if(TempData[SomePageModel.MessageKey] is string message)
{
<p>#message</p>
}
<form method="POST">
<button type="submit">POST!</button>
</form>
SomePage.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace temp.Pages
{
public class SomePageModel : PageModel
{
public const string MessageKey = nameof(MessageKey);
public void OnGet() { }
public IActionResult OnPost() {
TempData[MessageKey] = "POST Success!";
return RedirectToAction(Request.Path); // redirect to the GET
}
}
}
This pattern also works for HTTP methods such as PUT and DELETE. Simply substitute any other HTTP verb; for instance, we can do a Put-Redirect-Get.

Related

POST Form Data to Blazor razor component (application/x-www-form-urlencoded)

I just started learning Blazor so please be patient with me if the question is strange.
Is it possible to POST Data as content-type "application/x-www-form-urlencoded" to Blazor razor component so when the page is being opened in browser it will show the provided initial values by the caller? It works well when using querystring and calling razor component url with HTTP GET method and with help of navigationManager. In this case I am not able to change how the data will be sent. I need to be able to handle a HTTP POST call with content-type application/x-www-form-urlencoded and the body providing initial value as a key=value. Data shall be showing on screen when page is loaded. User should then be given some options on page and selecting by clicking buttons.
If this is not possible what would be the proper approach for this specific requirement, i.e. cannot change how data is being sent (must be HTTP POST with content-type application/x-www-form-urlencoded) and receiving application being Blazor.
Update: The Blazor app should preferably be server-side but can be changed to web assembly (client-side) if required.
In Blazor Server, in-app navigation is done via websocket, there is no HTTP request made, thus no GET or POST action. You can only handle external HTTP requests, which should be exactly the case in question.
Blazor Components, or actually Razor Components, despite some of them act like pages with the #page tag, are just components. They do not live independently, but have to be hosted in a Razor Page, i.e. your _Host.cshtml by default. Any external HTTP request to your Blazor app is actually a request to the hosting page, which in turn loads the corresponding page component depending on the request URI. These requests cannot be seen in the components, but they can be handled in the hosting page because it is just a plain old Razor Page.
To do this:
Create a PostFormService which passes the post form between the host page and your components:
using Microsoft.AspNetCore.Http;
public class PostFormService
{
public IFormCollection? Form { get; set; }
}
Register the PostFormService to the DI. In the ConfigureServices method in Startup.cs, add:
services.AddScoped<PostFormService>();
Add the following code block to your host page:
#using Microsoft.AspNetCore.Mvc.RazorPages;
<!-- ignore anti-forgery token for external post requests -->
#attribute [IgnoreAntiforgeryToken]
<!-- specify model for the page -->
#model HostPageModel
#{
public class HostPageModel : PageModel
{
// postFormService is injected by the DI
public HostPageModel(PostFormService postFormService)
{
PostFormService = postFormService;
}
private PostFormService PostFormService { get; }
public void OnPost()
{
// store the post form in the PostFormService
PostFormService.Form = Request.Form;
}
}
}
Now you can inject PostFormService into your Razor Components and access the request form:
#inject PostFormService PostFormService;
#code{
protected override void OnInitialized()
{
base.OnInitialized();
// PostFormService.Form will be null if the page is not requested by
// a POST method
var data = PostFormService.Form?["data"];
Console.WriteLine(data);
}
}
Sounds like you are looking for an MVC flavoured solution but implemented in a Blazor page component- So am I currently. A Blazor post request using an EditForm or just a vanilla HTML submit action is an easy topic to find guidance on, but equipping a Blazor page component such that it can process incoming form body data as if it were an MVC controller [HttpPost] decorated method is a challenge. And yet, in some scenarios like an external card payment portal that redirects to your app when a transaction succeeds or fails, that is what you need. Many payment portals are only equipped to serve and post back to consumers with hidden input fields and form body key-value tuples as if it was 20 years ago! I feel your pain. I suspect we'll need a combination of MVC and Blazor functionality to achieve this.

Can't use Json() in asp.net core web api as it in asp.net core web

In asp.net core web I create a controller and I can use:
return Json(new {status=true});
but in asp.net core web API I can't do it.
In a controller:
[HttpGet("{id}")]
public JsonResult Get(int id)
{
}
I can not return Json()
How to use it?
Asp.Net Core Web API does provide support for wide varieties of response types, with Json being one among them. You can do that like shown below. Make sure you have all your required dependencies. You can learn about the dependencies from the documentation link I attached in this answer.
[HttpGet]
public IActionResult Get()
{
return Json(model);
}
You can also specify strict response formats using the [Produces] Filter on your controller.
Configuring Custom Formatters
You can also configure your own custom formatters in Asp.Net Web API project by calling the .AddFormatterMappings() from ConfigureServices method inside of your Startup.cs. This allows for a greater control on your content negotiation part and lets you achieve strict restrictions.
Please go through this documentation to understand further.
Using Responses with Status Codes
However, when using Web API, I suggest you use the helper methods that are built in so that your response becomes more expressive as it contains both the response content along with the status code. An example of how to do that is below
[HttpGet]
public ActionResult Get()
{
return Ok(_authors.List());
}
For a full list of helper methods available, you can take a look at the Controller.cs and ControllerBase.cs classes.
Asp.net core web api inherit from controllerBase, which doesn't contain a Json(Object) method. You should initialize a new JsonResult yourself in the action.
[HttpGet("{id}")]
public JsonResult Get(int id)
{
return new JsonResult(new { status = true });
}

How to redirect to action in ASP.NET Core WebAPI?

I've got two actions in my ASP.NET Core Web API application's controller:
[HttpGet("get-all")]
public IActionResult GetAll() { ... }
and
[HttpDelete("{id}")]
public IActionResult Delete(int id)
{
...
return RedirectToAction("GetAll");
}
Delete action always redirects to itself and never to GetAll. Why so? In the same time similar redirect from Post action works ok.
Can't find any docs on the subject. Any help?
Have you tried to use RedirectToActionResult? Like this (change ControllerName with your actual Controller's name ):
RedirectToActionResult("GetAll", "ControllerName", null);
Documentation
Hope you'll find this useful.

Trying to implement a Breeze controller in asp.net mvc

I am trying to implement a simple Breeze controller in Asp.Net MVC4, but can't seem to access it. Is it possibly conflicting with .Net's standard Web.Api ?
If my url is http://localhost:49479/api/values then I get a good return value from Web Api.
However if my url is http://localhost:49479/breeze/Breeze I get "Http 404" error "Resource not found".
If my url is http://localhost:49479/breeze/Breeze/5 I get error No HTTP resource was found that matches the request URI 'http://localhost:49479/breeze/Breeze/5'.
Your advice is greatly appreciate.
Here's what I have in ..Controllers/BreezeController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Breeze.ContextProvider;
using Breeze.WebApi2;
using Newtonsoft.Json;
namespace RageSys.Controllers
{
[BreezeController]
public class BreeezeController : ApiController
{
// GET api/values
public string Get(int id)
{
return "value";
}
public IEnumerable<string> GetMtm(int id)
{
return new string[] { "value1", "value2" };
}
}
}
and in BreezeWebApiConfig.cs :
using System.Web.Http;
[assembly: WebActivator.PreApplicationStartMethod(
typeof(RageSys.App_Start.BreezeWebApiConfig), "RegisterBreezePreStart")]
namespace RageSys.App_Start {
///<summary>
/// Inserts the Breeze Web API controller route at the front of all Web API routes
///</summary>
public static class BreezeWebApiConfig {
public static void RegisterBreezePreStart() {
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "breeze/{controller}/{action}"
);
}
}
}
The result you are getting from your api/values request is not coming from the listed controller. You must have the default ValuesController and WebApiConfig (which defines a route that takes a parameter) still in your project.
You do not have a route for http://localhost:49479/breeze/Breeze/5. The third segment (currently 5) needs to be the name of an Action method. For you, that means GetMtm. You do not have a route that takes any parameters, so you'll get nothing from: http://localhost:49479/breeze/Breeze/GetMtm/5 unless you define such a route. You probably don't want to do this though, because Breeze coupled with Entity Framework will make life very easy. You should implement the simplest possible Breeze / Entity Framework application and see how it works from there.
If you are using parameters and using Breeze, then ensure you use the .withParameters({ ParameterName: "Fred"}) or .withParameters({ id: id-value}), for example, in your Breeze query and ensure the parameter name in your function to be called (GetMtm in your case) at the server matches the parameter name you are using at the client.

Using PUT verb in edit form using ASP.NET MVC 4 and Restful Routing .NET

I'm using the Restful Routing .NET NuGet package (https://github.com/stevehodgkiss/restful-routing) in my ASP.NET MVC 4 project. According to the documentation, I should be able to submit a form using the PUT verb to the Update action in a controller by placing the #HTML.PutOverrideTag() in the form. I have not been able to get this to work. Every time I submit the form I get a 404 Not Found error. Can anyone confirm whether they have been able to get this working properly? My code is below:
routeconfig.cs:
map.Resources<UsersController>();
views\users\edit.cshtml:
#using (Html.BeginForm("update", "users", new { id = Model.Id }))
{
#Html.PutOverrideTag()
<input id="user_submit" name="commit" type="submit" value="Update" />
}
UsersController.cs:
[Authorize]
[HttpGet]
public ActionResult Edit(int id)
{
var user = UserRepository.GetById(id);
return View(user);
}
[Authorize]
[HttpPut]
public ActionResult Update(int id, User user)
{
return View("edit", user);
}
Steps to recreate:
Browse to: /user/edit
Form displays
Press submit button
Receive 404 Not Found error
Try
#Html.HttpMethodOverride(HttpVerbs.Put)
instead of
#Html.PutOverrideTag()