ASP NET Core - Working With XML Results On Web APIs
January 29, 2025
• 1,422 views
aspasp netasp net coreasp.netasp.net coredotnetasp.net core web apiasp.net training videos.net coreasp.net web apiprogrammingdotnet coreminimal apinick chapsassoftware engineeringminimal api vs controllerminimal api tutorialdotnet minimal apisminimal api dotnet 6minimal api dotnet 8minimal api dotnet 7minimal api dotnet 9minimal api dotnet 10xmlmime typemime typesasp net xmlxml resultxml apiweb apidotnet web api
JSON is the way of the web API! But... What about XML? Surely we no longer need to be concerned with that?
Well... There are still some use cases! Check out this video for returning XML data from web APIs in ASP NET Core.
View Transcript
in this video we're going to look at building a web API that can return XML in C and I know what you're thinking XML why the heck do we want to return XML isn't everyone using Json and you're mostly right except there are still some things that use XML hi my name is Nick centino and I'm a principal software engineering manager at Microsoft recently when I was working on my blog which is built on Steven gel's Blazer blog engine I found myself having to make some changes that needed to return XML on a web API if you're not famili with having your own blog or building your own website this way having something like a Sit map is very helpful for search engines and that's built in XML not only sit Maps but if you want to have an RSS feed that's also using XML
so XML is still used not everything is Json so in this video we're going to be looking at different ways so we can return XML from a minimal API and from a controller and that way you can compare and contrast these different mechanisms if that sounds interesting just a reminder to subscribe to the channel and check out that pin comment for my courses on dome train now let's jump over to visual studio and play with some minimal apis all right in Visual Studio here you can see that I have a minimal API set up from line 12 to 20 you'll also notice if you look a little bit above that I have some code to be able to map controllers and add controllers and that's because in just a moment we'll be looking at that as well if we look at this minimal API that
I have it's just going to be at the root so no dedicated path for that I'm just going to show that we can technically return a string that has some XML in it and we'll see what that looks like and then continue to build onp top of this so I'm going to go ahead and run this and it's probably going to be pretty obvious to you what happens here but it's still worth us going through all right when I head over to our route what we can see here is that I have this text coming back exactly as you might have expected nothing too fancy here however if you're not familiar with looking at this kind of stuff in a browser versus calling it from a programmatic API the thing that we need to call out here is that this is just plain text and
we don't have a content type so that will mean that in terms of the browser it just sees it as plain text and if we're working with an API there's no extra information to indicate sort of the content type or the format that this data is in now this is an XML and we do have a mime type that can support that so let's go back to the code and make sure we can configure that properly the most common way that we generally do this kind of thing is we would say something like results and then we would say something like okay because we're returning a 200 then we put in the contents and there's no actual overload that lets us specify the mime type here that means that it's just going to be plain text every single time so we don't have access to
doing that with results. but we do have some other things we can use all right so what I'm going to be doing instead of saying results. okay is doing results. file results. file takes in a stream it could also be a file path and we're going to specify application XML as the mime type so that will mean that we can use a stream here and we're going to use this string here in Contents which is the XML content we have we're going to convert that two bytes and then wrap it in a memory stream that will allow us to basically take this string here from line 14 and feed it back on the minimal API and this time we're going to have the content type specified so if we go run this one more time we should be able to see that it looks a
little bit different it should still be the same string but the format will be different in the browser let's go ahead and refresh and we can see that it says that it is XML right so it's saying it doesn't have any style information associated with it but you can see that the browser truly does understand that it's an XML rure now so we're one step further in being able to do this properly let's go back to visual studio and check out what we can do with the controller okay from line 21 down to 31 I have a controller here the route that we're going to be hitting is now slash controller just to give it a different route for us and you'll notice that the body of this is almost identical it's just that because we're inheriting from controller base here I don't have to
have results. file in fact this is going to be an i result if you look at the intellisense when I'm hovering over this in the tool tip and that means if I go down to here you can see it's ey action result so this is slightly different they're not the exact same thing but this is essentially the same mechanism so if I were to go run this now and go to slash controller we will get the exact same result so let's go do that very quickly all right so if I head to this route now press enter you can see that it did finish loading and it's the exact same thing so both the minimal API and the controller work with this type of format now at this point that's not super exciting we're able to basically just return a string and now we can
tell the browser or the caller the mime type or the content type that we're dealing with so that's a step forward that's all nice however if we're reflecting back to the scenario that I personally started with I need to be able to return a sitemap and I needed to be able to return an RSS feed both of these things are XML documents now the tricky thing is that I didn't want to have to go essentially write this custom XML into a string every single time I didn't want to have to format it that way in fact I never want to have to think about that so as we go forward in the rest of this video we're going to be looking at some ways that we can enhance our ability to return XML on minimal apis okay so the next step that we're going to
be doing then is serialization so I have a new route that I've introduced here right on L 19 called SLS serialize so that's what we'll be going to next and what you'll see in the body of this is that I'm actually doing something a little bit different I'm no longer just hardcoding a string that has some XML inside of it and instead what I'm doing is I'm making a new XML serializer and this is just built in in system XML serialization and then I can make it based on the type of XML record now XML record is going to be something that I've created if I scroll down a little bit lower you can see that I have a class called XML record it needs to have a public parameterless Constructor and then I have message on it which is just a string value this
is going to be almost mapping to what we had in the browser it's just that I'm calling it XML record and not XML so we don't have a funny naming conflict but that's just a minor detail you'll see in just a moment that it comes out to being roughly the same type of thing so I make a new instance of this record and essentially what I'm trying to show you is that this here from line 22 to 25 will end up mapping roughly to something that looks like what we have on line 15 here if we go down a little bit lower you can see that I make a new memory stream and then you can see that on line 27 I'm asking the serializer to serialize that record that we have here into the stream I've also just noticed that I had a capital
S on that that's going to drive me nuts so I'm changing it on the Fly here what we do after that is we set the stream position back to zero so that we have a stream populated with the data that we need and we're saying that that stream is currently at the beginning and that way when we go to send it back again using results. file which is what we saw in the previous example up here on line 17 exact same idea that stream is now going to be a string having our XML data in it before we move on this is just a quick reminder that I do have a course on C refactoring available on dome train refactoring is one of the most critical skills that you can learn as a software engineer and this helps you continue to build upon applications that
already exist making sure that they can scale and have extensibility I walk you through a bunch of various techniques and give you some examples that we walk through together to see how we can apply these techniques to refactor the code check out the pin comment and the links in the description to get this course now back to the video essentially all that we're doing is taking an object and conver converting it into an XML string everything else is essentially what we've already seen especially having this mind type let's go run this and go to SL serialize now if I head over to SL serialize and press enter you'll see that it was almost the same little bit of extra information here this is going to be some of the schema information and then you'll notice it's also now XML record and it's with a capital
x if I go back you'll see that it's almost the same right but this is just because of how the serialization was working I named things with this casing and that's why it's coming out that way but this information with the schema is just extra so in the end what we were able to do here is take an object that we had in memory and serialize it into a string I didn't have to go manually by hand try and construct this string cuz that would be a bit of a pain in the butt especially if you're considering that a site map gets pretty tricky just to briefly show you if I go over to my website Dev leader.com entries in here I can tell you right now I'm not about to go build up this site map By Hand by modifying a string or using
a string Builder absolutely no way I would just rather ask a serializer to go do all of that work for me but let's go back to visual studio and talk about making this a little bit better so the thing that I really don't like about this is that if I have multiple things that I want to have returning XML it basically means that I have to have this pattern sort of copied and pasted everywhere it's a kind of ugly solution it gets the job done but I don't like having to have the same type of thing everywhere and like I said in terms of reading what this is doing yeah we can tell what it's doing but it's not very nice overall I mentioned that in my use case I needed a sitemap I also needed to have my RSS feed those are two things
that I would essentially have to do something just like this of course building up this data type that I have to go return would look different but ultimately I'd have all this other code around here just to be able to return an XML document now wouldn't it be nice that if instead of saying something like results. file I could instead say something like results.xml and just return the object that I want as XML it's almost like when we have results. okay we can give it an object and it goes back as Json I think that would be awesome to be able to have so let's try and build that this is going to be a solution that I've taken from Andrew Lock who has a blog post on this Andrew Lock has tons of awesome blog post with tons of helpful CP and.net tips this
is exactly where this thought came from we were able to build an XML result which inherits from I result which means we can go use that on our minimal API and you'll see that we're able to use a serializer here and it's going to be based off of the type T because this is going to be a generic type what we're able to do is create this and pass in the instance that we want to work with and set that to being the result now the I result has this execute async which takes in the HTTP context which we can see here and then we have a little bit of a null check here so we'll throw up that context it's null shouldn't have to worry about that though and then the other part that is going to look quite familiar is right down here
where we have the memory stream we're going to ask that serializer to do the serialization for us so exact same thing we saw earlier we're now going to set the response content type to being the XML mime type here so that's happening on line 71 this is instead of us saying results. file and passing in the type or able to actually specify that rate on response. content type we're going to reset that stream position back to zero and then copy that stream into the body ultimately the body is the thing that we need to populate on the response because that's what gets sent back to the caller so doing stream. copy to async is going to take the stream that we've just filled from the serializer and copy that over to the responses body this is essentially everything that we've already built but now we
get to package this up into something that's nice all right so how would this look well if I wanted to do XML result which we have here I can go say an XML result of XML record which is going to be the type that we have right up here I can go make a new one so we'll call it result equals new and then I will pass in our record that we have here then from there I can return result this will essentially give us the same type of thing that we had before instead of having all of this code up here that we would have to copy and paste anything we want to return XML we now have this little short form way where we can make a new XML result and return it on the minimal API so let's go ahead and press
play and see if this works okay moment of truth let's go ahead and refresh this page and voila we have the exact same thing which doesn't seem that exciting but the fact that it is the exact same thing is what we want we wanted this exact Behavior but to wrap it up in an XML result but there's one more thing we can do and I wanted to show you how to make this feel a little bit closer to results. something cuz in this case what we were doing was making a new object and what I would like to do instead is just say return results. something and give us that familiar workflow to illustrate what I mean if we look on line 30 we can see return results. file what I would love to be able to do is say something like return and then
results.xml something like that pass in result and then it's all nice on one line just like this just like we would have had before on line 30 that's what I would like to get to the the problem is that this results type is actually going to be static here so how we were doing results. file this is a static method call and the unfortunate thing is that we can't extend this we can't go add an extension method called XML but we can do something else because they thought about this ahead of time what we can do is say results. extensions and extensions if we have a close look is going to be I result extensions so this allows us to go make make an extension method on this because we can extend IR res extensions this is a great idea so this is what I
would like to have but we don't have the extension method yet so how do we go do that and I stand corrected I should have said record needs to be inside of here that's what I get for naming my variables almost the same thing so this is what we want how do we get it well as I hinted the answer is with an extension method so we can go make a new static class called XML result extensions you can call this whatever you would like as long as the name doesn't conflict and then we can say public static I result because that's going to be the return type then we can say XML because that's going to be the name of the static method we want to call and then we need this which is going to be the keyword that we need to use
for an extension method if you're not familiar with that and that's going to be result extensions type and then we don't actually need to use this at all because we're not taking any operations on that instance but we also need to pass in the thing that we want to be wrapped and converted into XML once we have result we can go pass that into a new instance of our XML result this is essentially what we had on the line above and now we're just converting it over to being an extension method so if I scroll back up here you can see that this now compiles if we go clean this up get rid of all that look at how nice and succinct that looks that's a way better solution in my opinion than having to go build up a string of XML like this and
then having everyone have to know that they need to go convert it to a stream and then they also have to pass in the mime type instead we can just build up what we need have a serializer take care of it for us using an extension method and a custom result type let's go run this and see if it works moment of truth if I press enter here hopefully we get the same result and we do it's the exact same sometimes boring results are the results that we want so in this video we looked at several different ways that we can return a string that's holding XML inside of it we initially looked at the fact that we want to make sure that we have the MIM type specified is applications XML and that way callers know the content type from the HTTP request that
they're dealing with from there though we wanted to make it a little bit more streamlined for use so instead of having to build up a string if we just want to use a serializer how do we do that instead and how can we make that all wrapped up into a nice easy way to call now I'm not telling you that building up by a string or using a string Builder is the wrong way to do it but for my own use cases I didn't want to have to worry about that you may very well be able to use a string Builder write your own serialization and make it way more performant that might be something that you want to explore for your use case but in my use case I just want Simplicity I just want to be able to go build my S map
just like this pass it into this nice simple extension method and then I'm going to be using a caching layer on top of this anyway in my own use case so this worked very well for me and I wanted to share with you how you can return XML on minimal apis thanks for watching I'll see you next time
Frequently Asked Questions
Why would I want to return XML from a web API instead of JSON?
While JSON is widely used, there are still scenarios where XML is necessary, such as when creating sitemaps or RSS feeds. These formats are inherently XML-based, and using XML ensures compatibility with systems that require it.
How can I specify the content type for XML in my API response?
To specify the content type for XML, I use the `results.file` method in my API and set the MIME type to `application/xml`. This way, the browser or any API caller knows that the response is in XML format.
What is the benefit of using an XML serializer instead of manually constructing XML strings?
These FAQs were generated by AI from the video transcript.Using an XML serializer simplifies the process of generating XML. It allows me to convert objects directly into XML format without having to manually build the XML structure, which can be error-prone and tedious, especially for complex data.
