Is it considered a good practice to use [FromBody] in the backend to identify a parameter in a WebAPI?

I have a front-end WebAPI built with Angular and TypeScript that has the following structure.

    removeSubset(id: number): ng.IPromise<any> {
        return this.$http.post(this.api + '/DeleteStudySubset', id)
            .then(this.returnData);
    }

    returnData = (response: any) => {
        return response.data;
    };

The corresponding back-end version is structured as follows:

    [HttpPost]
    [ResponseType(typeof(IHttpActionResult))]
    public async Task<IHttpActionResult> DeleteStudySubset(int id)
    {
        await _subsetRepo.DeleteStudySubset(id);
        return Ok();
    }

Initially, I encountered a URI 404 Error and struggled to find a solution. Eventually, I discovered the parameter binding [FromBody] attribute, which resolved the 404 issue.

Therefore, I updated the back-end API to include the attribute like this:

    [HttpPost]
    [ResponseType(typeof(IHttpActionResult))]
    public async Task<IHttpActionResult> DeleteStudySubset([FromBody]int id)
    {
        await _subsetRepo.DeleteStudySubset(id);
        return Ok();
    }

Based on my limited understanding, it seems that [FromBody] instructs the back end to parse the body of the incoming request instead of relying solely on the URL. Is this correct? I may not be articulating my comprehension effectively.

In essence, my main question is whether using the [FromBody] attribute to address the 404 error is considered best practice or merely a temporary fix. I am concerned that it might be masking an underlying configuration issue between my front-end and back-end APIs rather than resolving it effectively.

Answer №1

It seems like your TypeScript code is currently performing a POST request and sending the ID in the body, which is causing a 404 error. To fix this issue, consider changing the TypeScript code to make a GET request instead. You can pass the ID as a parameter in the URL of the GET call. Alternatively, for better adherence to RESTful principles, it would be recommended to use DELETE HTTP requests for deletion actions. Modify the backend method to use HttpDelete and adjust the TypeScript code to send a DELETE request. The second option may be the preferable approach.

Answer №2

When designing your WebApi to be RESTful, it is important to view routes as addresses for entities and http verbs as actions. The use of FromBody should be limited to HttpPost when creating an entity.

To make your controller more organized, consider decorating it with a route prefix using attribute routing [RoutePrefix()]. If you are working with WebApi 2, make sure to enable attribute routing. If not, look into how to enable this feature.

[RoutePrefix("api/study-subset")]

Add the route to your method by using attribute routing [Route()]. You do not need to include the [HttpDelete] attribute, as WebApi will automatically recognize the Delete keyword from the method name. The id parameter will be extracted from the route and passed into your method. If the id is not included in the route, it will be treated as part of the query string.

[Route("{id}")]
public async Task<IHttpActionResult> DeleteStudySubset(int id)
{
    await _subsetRepo.DeleteStudySubset(id);
    return Ok();
}

Finally, update your TypeScript code to reflect these changes:

return this.$http.delete(this.api + 'api/study-subset/' + id)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best approach to defining document interfaces with Typescript and Mongodb?

Imagine a straightforward user database setup: // db.ts export interface User { _id: mongodb.ObjectId; username: string; password: string; somethingElse: string; } // user.ts import {User} from "../db" router.get("/:id", async (re ...

Searching for a particular element in a JSON array using C#

Can anyone help me with searching for a specific device (e.g. AEVL2020) in a json file and retrieving multiple results based on "registers"? I've tried looking online but couldn't find any useful information. "12":{ "user_id": " ...

Having difficulty transferring types to and from a custom module?

I'm currently faced with an issue while working on a typescript module within a larger monorepo. I am having difficulty importing types from one package into another via node modules. The types are located at ./types, and my package.json contains a ke ...

What is the process for retrieving an array from JavaScript using the ExecuteScript function?

While returning a string may be easy, I am struggling to figure out how to return an array. Below is an example that is not working (myURLs is a global array variable): List<object> list = ((IJavaScriptExecutor)driver).ExecuteScript( ...

Sort through object list and connect it to datagrid

I am working on a project where I have an object that includes a list. This list is currently linked to a datagrid in my WPF application. My goal is to display two datagrids that are connected to the same object List but show different types of data. The ...

Issue encountered during Angular unit test execution

I encountered an issue while conducting unit testing in Angular. I am attempting to test the creation of a component. Please refer to the error below and help me understand why this problem is occurring. I have also imported the necessary services related ...

Modify data in a table using Dialog Component in Angular Material

I need to implement a Material Dialog feature that allows users to update entries in a table by clicking on the "Change Status" button. Check out this functional snippet: https://stackblitz.com/edit/angular-alu8pa I have successfully retrieved data fr ...

Tab-less WPF Tab Control - A Unique User Interface

I'm interested in creating a control that functions like a tab control, but without the traditional "TabStrip" component. Instead, I would like to be able to change the tabs using a combo box. How can I achieve this? I'm sure there's a solu ...

The functionality of the button for selecting and deselecting all checkboxes is currently malfunctioning

I have a button in my ng-grid that successfully selects all checkboxes. However, I am also trying to implement functionality to deselect the checkboxes using the same button. Here is the initial code: app.directive('selectAll',function(){ ret ...

Deploying an Angular application on IIS Web Server

I'm currently working on a project using AngularJS and node.js. I've successfully compiled my application (shown as app in the image below) using gulp, resulting in the directories displayed. https://i.sstatic.net/8gbhk.png Now I'm at a st ...

I am interested in utilizing Template literal types to symbolize placeholders

Currently, I am in the process of converting existing javascript files into typescript for my business needs. Below is an example object structure: [ { // Sample column names givenName, familyName, and picture are provided as examples. "giv ...

Angular 2 and TypeScript: Mastering Checkbox Data Binding

Below is the HTML view in which user roles are checked. I want to bind a table of modified user roles using the actualizeRoles() method. How can I achieve this? <md-accordion class="example-headers-align"> <md-expansion-panel hideToggle=" ...

Sending a form using ng-model with ng-repeat and ng-if conditions

How can I effectively submit a form in angular using ng-submit when also utilizing ng-repeat and ng-if? The issue arises with the disappearing of the input option containing ng-model due to ng-if. Below is a snippet of my code for better understanding: &l ...

Ways to integrate npm dependencies into your Cordova plugin

Currently working on implementing a Cordova plugin called core-cordova found in this repository. This particular plugin has a dependency on another NPM package. The issue arises after installing the plugin in my app using: $ cordova plugin add @aerogears ...

Connect hierarchical JSON using AngularJS

I'm facing an issue where I am attempting to bind JSON with two levels to a div using angular.js. The first level binds correctly, but the second level does not seem to be binding properly. Can someone please provide suggestions on how to adjust the b ...

Is it possible to assign an object literal to a typed variable in TypeScript? Can you also specify the typeof object literal?

Consider a scenario where you have the following type definition: type MyType = { A: number | string } If you try to assign a value like this, TypeScript will correctly flag it as an error: const myValue1: MyType = { A: 123, B: "Oh!", // This wil ...

Retrieve modified fields

Working with a ui-grid and making some edits to it, resulting in changes being made to the binded data within the grid. What would be the best approach for pushing this updated data back to the server? I believe the optimal solution would involve sending ...

choosing a file containing refined data from included files

Could you help me understand how to achieve the equivalent of this code snippet in C#? db.UserProfile.aggregate([ {$match:{_id:"sen"}}, { $project: { DemRole: { $filter: { input: "$DemRol ...

Increase Table Value Using Button

I have a table and a button, and I would like to increment the table with each click of the button. How can I achieve this? Here is an example of my table structure: <table> <tr> <td colspan="2"> Information </td></tr> <t ...

React - Login page briefly appears while loading

Hello, I have built a React application that consists of a Login page, Loading page, and the main app itself. However, there is a small issue where after a user logs in, instead of smoothly transitioning to the Loading page until the data is loaded, the L ...