The reason of the issue described here is the value passed to modificationDate
parameter of RangeFileContentResult
constructor:
return new RangeFileContentResult(media.Content, media.MimeType, media.Id.ToString(), DateTime.Now);
This date is used by the RangeFileResult
in order to create two headers:
ETag
- This header is an identifier used by browser and server to make sure that they are speaking about the same entity.Last-Modified
- This header informs the browser about the last modification date of the entity.
The fact that a DateTime.Now
is being passed every time the browser makes partial request might be a reason for ETag
and Last-Modified
headers values to change before the client will get the whole entity (usually if the entire process takes longer than one second).
In case described above, the browser is sending If-Range
header with the request. This header is telling the server that the entire entity should be resend if the entity tag (or modification date because If-Range
can carry either one of those two values) doesn't much. This is what happens in this case.
The fact that modification date is "dynamic" may also cause further issues if client decides to use one of following headers for verification: If-Modified-Since
, If-Unmodified-Since
, If-Match
, If-None-Match
.
The solution in this situation is to keep a modification date in database with the file to make sure it is consistent.
There is also a place for optimization here. Instead of grabbing the whole video from DB every time a partial request is being made, one can either cache it or grab only the relevant part (if the database engine which application is using allows such an operation). Such a mechanism can be used in order to create specialized action result by delivering from RangeFileResult
and overwriting WriteEntireEntity
and WriteEntityRange
methods.